开发者

How to have one java thread wait for the result of another thread?

I frequently need to have a thread wait for the result of another thread. Seems like there should be some support for this in java.util.concurrent, but I can't find it.

Exchanger is very close to what I'm talking about, but it's bi-directional. I only want Thread A to wait on Thread B, not have both wait on each other.

Yes, I know I can use a CountDownLatch or a Semaphore or Thread.wait() and then manage the result of the computation myself, 开发者_如何学Pythonbut it seems like I must be missing a convenience class somewhere.

What am I missing?

UPDATE

// 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);
}


Are you looking for Future<T>? That's the normal representation of a task which has (usually) been submitted to a work queue, but may not have completed yet. You can find out its completion status, block until it's finished, etc.

Look at ExecutorService for the normal way of obtaining futures. Note that this is focused on getting the result of an individual task, not rather than waiting for a thread to finish. A single thread may complete many tasks in its life time, of course - that's the whole point of a thread pool.


So far, it seems like BlockingQueue may be the best solution I've found.

eg.

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

The waiting thread will call queue.take() to wait for the result, and the producing queue will call queue.add() to submit the result.


The JDK doesn't provide a convenience class that provides the exact functionality you're looking for. However, it is actually fairly easy to write a small utility class to do just that.

You mentioned the CountDownLatch and your preference regarding it, but I would still suggest looking at it. You can build a small utility class (a "value synchronizer" if you will) pretty easily:

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
}


Since Java 8 you can use CompletableFuture<T>. Thread A can wait for a result using the blocking get() method, while Thread B can pass the result of computation using complete().

If Thread B encounters an exception while calculating the result, it can communicate this to Thread A by calling completeExceptionally().


What's inconvenient in using Thread.join()?


I recently had the same problem, tried using a Future then a CountdownLatch but settled on an Exchanger. They are supposed to allow two threads to swap data but there's no reason why one of those threads can't just pass a null.

In the end I think it was the cleanest solution, but it may depend on what exactly you are trying to achieve.


You might use java.util.concurrent.CountDownLatch for this.

http://download.oracle.com/javase/6/docs/api/java/util/concurrent/CountDownLatch.html

Example:

CountDownLatch latch = new CountDownLatch(1);

// thread one
// do some work
latch.countDown();

// thread two
latch.await();
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜