0

Future の静的リストを保持しようとしていますが、後で、進行中の Future を cancel() または notify() します。これらの Future に関連付けられている Callable クラスには wait() が含まれているため、続行するには外部ソースからそれぞれに通知する必要があります。ただし、呼び出し可能オブジェクトが待機ステートメントを通過しないため、notify() への私の呼び出しは無視されているようです。Futures のリストを持つクラスは次のようになります。

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 の参照と一致します)。

ここでは、同時実行の基本的な概念が欠けている可能性がありますが、条件 2 が満たされると、Callable が wait() 呼び出しを通過することを期待していました。

notify() の代わりに cancel() を使用すると、runnable が中断され、予想どおり InterruptedException が発生することに注意してください。

4

2 に答える 2

1

まったく同じオブジェクトnotifyが必要です。あなたの場合、オブジェクトに通知していますが、オブジェクトを待っています。残念ながら、オブジェクトがラップされていることを確認する簡単な方法がわからないため、オブジェクトがラップされるのを待つ必要はありません。FutureMyCallableMyCallableFuturewait()

解決策の 1 つは、ロック オブジェクトをコンストラクターに渡しMyCallable、関連付けられている .xml ファイルと共に保存すること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;
         ...
     }
  }
于 2012-06-04T18:44:08.240 に答える
0

あなたが達成しようとしているように見えるもの (私は間違っているかもしれませんが) は、SettableFutureのようなものです。

Executor への Callable の計算能力が必要かどうかはわかりませんが、SettableFuture は、他のスレッドがそこに座って別のスレッドが設定されるのを待っている間に、それを作成して準備ができたら設定するのと同じくらい簡単なはずです。

あなたが問題に近づいている2つのルートがあるようです。

1 つは Executor です。

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

もう 1 つのケースは、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 が設定されるまでスレッド 2 を待機させます。

于 2012-06-04T18:50:08.900 に答える