我试图持有一个静态的期货清单,并在以后取消()或通知()正在进行的期货。与这些期货相关联的Callable类在其中有一个wait(),因此每个必须由外部来源通知才能继续。但是,我对notify()的调用似乎被忽略了,因为callables永远不会超过他们的wait语句。具有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”与存储在静态列表中的未来引用相匹配)。
我可能在这里遗漏了一些基本的并发概念,但我预计当满足condition2时,我的Callable将继续通过wait()调用。
请注意,如果我使用cancel()而不是notify(),它会中断我的runnable并导致InterruptedException,正如我所料。
答案 0 :(得分:1)
您需要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;
...
}
}
答案 1 :(得分:0)
你似乎想要实现的目标(尽管我可能错了)类似于SettableFuture。
不确定你是否需要Callable到Executor的计算能力,但是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。