2011-07-12 41 views
2

我使用了一個事件系統的外部框架,爲簡單起見,假設它是這樣的:尋找與Java併發API事件同步的清潔解決方案

public interface EventListener { 
    public void eventA(int a); 
    public void eventB(int a, long b); 
} 

因此事件系統的屬性是在事件A之後,可能會或可能不會有相同的事件B.但是如果有事件B,那麼它需要在3000毫秒之內。

我不知道什麼乾淨的解決方案有針對這個問題,我看着在java.util.concurrency包,我沒有發現任何東西,能夠爲這個問題一個很好的清潔解決方案。我想我可能會使用Future<?>,但我不能提出一個很好的解決方案。

我將在僞代碼寫的東西我想做的事:

public void eventA(int a) { 
    // fired Event A 

    if (within the next 3 seconds there was an eventB for _exactly_ this a) 
     doSomething(a, b) 
    else 
     doSomething(a) 
} 

public void eventB(int a, long b) { 

} 

到目前爲止,我使用ConcurrentHashmap<Int, Long>,我存儲所有AB組合從eventB和我檢查,如果最後3000毫秒內我這樣的ab組合在eventA中,但我對這個解決方案並不滿意。我覺得需要使用Java 1.5更高級別的併發API來提供更簡潔的方式。

我會很高興提供一個乾淨的解決方案提示該問題。

+0

如果你調用'doSomething(a)',然後2秒後'doSomething(a,b)'爲同樣的'a',會發生什麼?這是可以接受的行爲嗎? –

+0

Tikitaka Salinas? – edutesoy

+0

請使用比「a」,「b」和「doSomething」更多的描述性名稱。否則很難理解你試圖達到的目標。 –

回答

0

如何使用包含一個地圖,對每個接收到的事件A,一個對象(讓我們稱之爲Foo)含在該A被接收的時間,以及潛在Bnull最初)。

當您收到一個事件A,您創建一個Foo實例與當前時間和空B,你把它存儲在地圖上,你啓動休眠3秒,然後一個線程檢查是否有相關的FooA包含B,從地圖中刪除條目,並相應地執行操作(即使用適當的參數調用doSomething)。

當您收到B,你檢查是否有在地圖中Foo,如果它已經不到3秒的Foo被接收時(儘管這不應該發生),並存儲B

您當然必須在需要時進行同步。

1

我不完全確定你是否需要它像這樣工作,但其背後的邏輯是,當eventB被觸發時,它將數據添加到一個ConcurrentHashMap中,並計劃在3秒後移除它自己。當eventA被觸發時,它將從地圖中刪除數據(從而清除該鍵的事件),如果有事件,則調用doSomething(int,long),否則調用doSomething(int)。

import java.util.concurrent.*; 

public class EventListenerImpl implements EventListener { 

    // You can change how many threads there are, or use a scheduler that's 
    // already in the application. 
    private final static ScheduledExecutorService scheduler = Executors 
      .newScheduledThreadPool(1); 

    private ConcurrentHashMap<Integer, Data> data = new ConcurrentHashMap<Integer, Data>(); 

    @Override 
    public void eventA(int a) { 

     Data b = data.remove(a); 
     if (b != null) { 
      doSomething(a, b.getB()); 
     } else { 
      doSomething(a); 
     } 

    } 

    @Override 
    public void eventB(final int a, final long b) { 

     final Data thisData = new Data(a); 

     // Needs to be synchronized because it may be removed by a scheduled event 
     synchronized (data) { 
      Data d = data.put(a, thisData); 
      if (d != null) { 
       d.getFuture().cancel(true); 
      } 
     } 

     thisData.setFuture(scheduler.schedule(new Runnable() { 

      @Override 
      public void run() { 
       data.remove(a, thisData); 
      } 

     }, 3, TimeUnit.SECONDS)); 

    } 

    private class Data { 
     private long b; 
     private ScheduledFuture<?> future; 

     public Data(long b) { 
      this.b = b; 

     } 

     public long getB() { 
      return b; 
     } 

     public void setFuture(ScheduledFuture<?> future) { 
      this.future = future; 
     } 

     public ScheduledFuture<?> getFuture() { 
      return future; 
     } 
    } 
} 

讓我知道這是不是你需要的東西相當,因爲我是一個有點困惑,並結束了猜測是你所試圖做的。例如,如果a不是某種類型的關鍵字,那麼這可以被大大簡化......如果eventA在調用doSomething之前等待三秒,而不是始終跟蹤最後三秒,那麼它也可以被簡化。