5

我经常需要让一个线程等待另一个线程的结果。似乎在 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);
}
4

7 回答 7

7

你在找Future<T>吗?这是已(通常)提交到工作队列但可能尚未完成的任务的正常表示。你可以找出它的完成状态,阻塞直到它完成,等等。

寻找ExecutorService获得期货的正常方式。请注意,这侧重于获取单个任务的结果,而不是等待线程完成。当然,单个线程可以在其生命周期内完成许多任务——这就是线程池的全部意义所在。

于 2011-03-07T16:36:59.503 回答
5

到目前为止,似乎BlockingQueue可能是我找到的最佳解决方案。

例如。

BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(1);

等待线程调用queue.take()等待结果,生产队列调用queue.add()提交结果。

于 2011-03-07T16:42:42.823 回答
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
}
于 2011-03-07T20:11:14.143 回答
2

从 Java 8 开始,您可以使用CompletableFuture<T>. get()线程 A 可以使用阻塞方法等待结果,而线程 B 可以使用complete().

如果线程 B 在计算结果时遇到异常,它可以通过调用将其传达给线程completeExceptionally()A。

于 2017-09-04T03:02:06.620 回答
0

使用有什么不方便Thread.join()

于 2011-03-07T16:37:29.117 回答
0

我最近遇到了同样的问题,尝试使用 Future 然后使用 CountdownLatch 但选择了 Exchanger。它们应该允许两个线程交换数据,但是没有理由为什么其中一个线程不能只传递一个空值。

最后,我认为这是最干净的解决方案,但这可能取决于您到底想要实现什么。

于 2011-03-07T16:41:15.397 回答
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();
于 2011-03-07T17:14:45.763 回答