我经常需要一个线程等待另一个线程的结果。似乎在java.util.concurrent中应该有一些支持,但我找不到它。
Exchanger非常接近我所说的,但它是双向的。我只希望线程A在线程B上等待,而不是彼此等待。
是的,我知道我可以使用CountDownLatch或Semaphore或Thread.wait()然后自己管理计算结果,但似乎我必须在某处错过一个便利类。
我错过了什么?
更新
// An Example which works using Exchanger
// but you would think there would be uni-directional solution
protected Exchanger<Integer> exchanger = new Exchanger<Integer>();
public void threadA() {
// perform some computations
int result = ...;
exchanger.exchange(result);
}
public void threadB() {
// retrieve the result of threadA
int resultOfA = exchanger.exchange(null);
}
答案 0 :(得分:7)
您在寻找Future<T>
吗?这是(通常)已提交到工作队列但尚未完成的任务的正常表示。你可以找到它的完成状态,阻止它完成,等等。
查看ExecutorService
获取期货的正常方式。请注意,这主要集中在获取单个任务的结果,而不是等待线程完成。当然,单个线程可以在其生命周期内完成许多任务 - 这是线程池的重点。
答案 1 :(得分:5)
到目前为止,似乎BlockingQueue可能是我找到的最佳解决方案。
例如
BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(1);
等待线程将调用queue.take()
等待结果,生成队列将调用queue.add()
来提交结果。
答案 2 :(得分:4)
JDK不提供提供您正在寻找的确切功能的便捷类。但是,实际上编写一个小实用程序类实际上相当容易。
您提到了CountDownLatch以及您对此的偏好,但我仍然建议您查看它。您可以非常轻松地构建一个小型实用程序类(如果愿意,可以构建一个“值同步器”):
public class OneShotValueSynchronizer<T> {
private volatile T value;
private final CountDownLatch set = new CountDownLatch(1);
public T get() throws InterruptedException {
set.await();
return value;
}
public synchronized void set(T value) {
if (set.getCount() > 0) {
this.value = value;
set.countDown();
}
}
// more methods if needed
}
答案 3 :(得分:0)
使用Thread.join()
时有什么不方便?
答案 4 :(得分:0)
我最近遇到了同样的问题,尝试使用Future然后使用CountdownLatch但是确定了一个Exchanger。它们应该允许两个线程交换数据,但没有理由为什么其中一个线程不能只传递null。
最后我认为这是最干净的解决方案,但这可能取决于你想要达到的目的。
答案 5 :(得分:0)
您可以使用java.util.concurrent.CountDownLatch。
http://download.oracle.com/javase/6/docs/api/java/util/concurrent/CountDownLatch.html
示例:
CountDownLatch latch = new CountDownLatch(1);
// thread one
// do some work
latch.countDown();
// thread two
latch.await();
答案 6 :(得分:0)
从Java 8开始,您可以使用CompletableFuture<T>
。线程A可以使用阻塞get()
方法等待结果,而线程B可以使用complete()
传递计算结果。
如果线程B在计算结果时遇到异常,它可以通过调用completeExceptionally()
将其传递给线程A.