如何让Java线程等待另一个线程的输出?

问题

我正在使用应用程序逻辑线程和数据库访问线程创建Java应用程序。它们都在应用程序的整个生命周期中持续存在,并且两者都需要同时运行(一个与服务器通信,一个与用户通信;当应用程序完全启动时,我需要它们才能工作)。

但是,在启动时,我需要确保最初应用程序线程等待直到db线程准备就绪(当前通过轮询自定义方法dbthread.isReady()确定)。我不介意app线程阻塞,直到db线程准备好。

Thread.join()看起来不像解决方案 - 数据库线程仅在应用程序关闭时退出。

while (!dbthread.isReady()) {}kind的工作,但空循环消耗了大量的处理器周期。

还有其他想法吗?谢谢。


#1 热门回答(126 赞)

使用aCountDownLatch,计数器为1。

CountDownLatch latch = new CountDownLatch(1);

现在在app线程中 -

latch.await();

在db线程中,完成后,执行 -

latch.countDown();

#2 热门回答(122 赞)

我真的建议你在多线程的神奇世界开始之前先阅读像Sun's Java Concurrency这样的教程。

还有很多好书(google为"Java中的并发编程","实践中的Java并发")。
得到你的答案:
在你必须等待dbThread的代码中,你必须具有以下内容:

//do some work
synchronized(objectYouNeedToLockOn){
    while (!dbThread.isReady()){
        objectYouNeedToLockOn.wait();
    }
}
//continue with work after dbThread is ready

在yourdbThread的方法中,你需要执行以下操作:

//do db work
synchronized(objectYouNeedToLockOn){
    //set ready flag to true (so isReady returns true)
    ready = true;
    objectYouNeedToLockOn.notifyAll();
}
//end thread run method here

我在这些例子中使用的objectYouNeedToLockOn最好是你需要从每个线程同时操作的对象,或者你可以为此目的创建一个单独的Object(我不建议让方法本身同步):

private final Object lock = new Object();
//now use lock in your synchronized blocks

为了进一步理解:
还有其他(有时更好的)方法来完成上述工作,例如: withCountdownLatches等。自Java 5以来,java.util.concurrent包和子包中有很多漂亮的并发类。你真的需要在网上找到材料来了解并发性,或者获得一本好书。


#3 热门回答(22 赞)

要求::

等待下一个线程的执行,直到上一个完成。无论时间消耗如何,下一个线程都不能在前一个线程停止之前启动。它必须简单易用。

答案::

@See java.util.concurrent.Future.get()doc。 future.get()在必要时等待计算完成,然后检索其结果。

任务完成!!见下面的例子

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.junit.Test;

public class ThreadTest {

    public void print(String m) {
        System.out.println(m);
    }

    public class One implements Callable<Integer> {

        public Integer call() throws Exception {
            print("One...");
            Thread.sleep(6000);
            print("One!!");
            return 100;
        }
    }

    public class Two implements Callable<String> {

        public String call() throws Exception {
            print("Two...");
            Thread.sleep(1000);
            print("Two!!");
            return "Done";
        }
    }

    public class Three implements Callable<Boolean> {

        public Boolean call() throws Exception {
            print("Three...");
            Thread.sleep(2000);
            print("Three!!");
            return true;
        }
    }

    /**
     * @See java.util.concurrent.Future.get() doc
     *      <p>
     *      Waits if necessary for the computation to complete, and then
     *      retrieves its result.
     */
    @Test
    public void poolRun() throws InterruptedException, ExecutionException {
        int n = 3;
        // Build a fixed number of thread pool
        ExecutorService pool = Executors.newFixedThreadPool(n);
        // Wait until One finishes it's task.
        pool.submit(new One()).get();
        // Wait until Two finishes it's task.
        pool.submit(new Two()).get();
        // Wait until Three finishes it's task.
        pool.submit(new Three()).get();
        pool.shutdown();
    }
}

该程序的输出::

One...
One!!
Two...
Two!!
Three...
Three!!

你可以看到在完成任务之前需要6秒,这比其他线程更大。所以Future.get()等待任务完成。

如果你不使用future.get(),它不会等待完成并执行基于时间的消耗。

祝你好运与Java并发。