繁体   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