簡體   English   中英

使用期貨地圖,如何在其中通知()一個元素?

[英]Using Map of Futures, how do I notify() a single element within?

我試圖持有一份期貨的靜態列表,並在以后的某個時間取消()或notify()正在進行的期貨。 與這些Future關聯的Callable類內部具有一個wait(),因此每個外部類都必須通知其繼續。 但是,我對notify()的調用似乎被忽略了,因為可調用對象永遠不會超過其wait語句。 帶有期貨列表的類如下所示:

private static Map <String, Future<Object>> results = new HashMap <String, Future<Object>>();

ExecutorService taskExecutor;

public void doStuff() {
    taskExecutor = Executors.newCachedThreadPool();

    // loop inifinitely - external processes will modify the conditions within
    while(!shutItDown) {

        if (<condition1>) {
            // condition 1 dictates the kick-off of a new callable
            Future<Object> future = taskExecutor.submit(new MyCallable(id));
            results.put(id, future);
        }
        else if (<condition2>) {
            // condition 2 represents a callable in a wait status needs
            // to be notified
            Future<Object> future = results.get(uid);
            if (future != null) {
                synchronized(future) {
                    future.notify();  // this doesn't have the desired effect!
                }
            }
        }
    }

}

Callable類目前只是一個模型,看起來類似於:

public class MyCallable implements Callable<Object> {

private String id;

public MyCallable(String id) {
    this.id = id;
}

@Override
public Object call() throws Exception {     

    try {

        // do some work here, then wait on outside notification

        synchronized(this) {
            this.wait();  // never gets past here!!!
        }

        // do some other work here, once this has been notified
    } 
    catch (InterruptedException e) {
        e.printStackTrace();
    }

    return null;
}

notify()方法被調用,但似乎沒有效果。 Future的對象引用似乎有效(即,局部變量“ future”與存儲在靜態列表中的Future的引用匹配)。

我可能在這里缺少並發性的一些基本概念,但是我希望當滿足condition2時,我的Callable可以繼續進行wait()調用。

請注意,如果我使用cancel()而不是notify(),它會中斷我的可運行程序並引起InterruptedException,這與我期望的一樣。

您需要notify 完全相同的對象。 在您的情況下,您正在通知Future對象,但正在等待MyCallable對象。 不幸的是,我不知道讓MyCallable對象看到其包裝的Future的任何簡便方法,因此不必等待它在其上進行wait()

一種解決方案是將一個鎖對象傳遞到MyCallable構造函數中,然后將其與關聯的Future一起保存。 就像是:

  private static Map <String, FutureLock> results =
        new HashMap <String, FutureLock>();
  ...
  Object lock = new Object();
  Future<Object> future = taskExecutor.submit(new MyCallable(id, lock));
  results.put(id, new FutureLock(future, lock));
  ...

  public class FutureLock {
      private Future<Object> future;
      private Object lock;
      public FutureLock(Future<Object> future, Object lock) {
         this.future = future;
         this.lock = lock;
      }
      public void notify() {
         synchronized (lock) {
            lock.notify();
         }
      }
      public Object get() throws Exception {
         return future.get();
      }
  }

  public class MyCallable {
     private Object lock;
     public MyCallable(String id, Object lock) {
         this.lock = lock;
         ...
     }
  }

您似乎想要實現的目標(盡管我可能錯了)類似於SettableFuture

不知道您是否需要執行器中的Callable的計算能力,但是SettableFuture應該像創建它並在其他線程坐在那里等待另一線程設置的准備就緒時一樣容易地進行設置。

您要解決此問題似乎有兩條路線。

一個是與執行者一起。

Executor e = Executors.newSingleThreadExecutor();
Future f = null;

線程1:

f = e.submit(new Callable(){
  public Object call(){
    return new Object();
  }
});

線程2:

f.get(); //will suspend Thread 2 until the Executor submits the callable

另一種情況是使用SettableFuture

final SettableFuture f = new SettableFuture();

線程1:

f.set(new Object());

線程2:

f.get(); //will suspend Thread 2 until Thread 1 set's the Future.

兩者都將實現相同類型的等待機制,不同之處在於第一個示例中的線程1將提交到單獨的線程來創建對象。 線程2仍將等待,直到另一個線程完成了該操作。 第二個示例將讓線程2等待線程1完成並設置Future。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM