如何让一个java线程等待另一个线程的结果?

时间:2011-03-07 16:34:43

标签: java multithreading java.util.concurrent

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

7 个答案:

答案 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.