当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何让Java线程等待另一个线程的输出?》经验,为你挑选了7个好方法。

我正在使用应用程序逻辑线程和数据库访问线程创建Java应用程序.他们都坚持为应用程序的整个生命周期,并都需要在同一时间运行(一个会谈到服务器,一个谈判给用户;当应用程序完全启动,我需要两个人工作).

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

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

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

还有其他想法吗?谢谢.



1> pdeva..:

使用计数器为1 的CountDownLatch.

CountDownLatch latch = new CountDownLatch(1);

现在在app线程中 -

latch.await();

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

latch.countDown();


我真的很喜欢这个简单的解决方案,尽管乍一看可能更难理解代码的含义.
此用法要求您在闩锁用完后重新制作.要获得类似于Windows中的可等待事件的用法,您应该尝试使用BooleanLatch或可重置的CountDownLatch:http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/AbstractQueuedSynchronizer. html http://stackoverflow.com/questions/6595835/resettable-countdownlatch-swap-in-equivilent

2> Herman Lintv..:

我建议您在开始进行多线程的神奇世界之前,先阅读Sun的Java Concurrency等教程.

还有很多好书(google为"Java中的并发编程","实践中的Java并发").

得到你的答案:

在你必须等待的代码中dbThread,你必须有这样的东西:

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

在你dbThread的方法中,你需要做这样的事情:

//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

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



3> Ash..:

要求::

    等待执行下一个线程直到上一个完成.

    无论时间消耗如何,下一个线程都必须在前一个线程停止之前才能启动.

    它必须简单易用.

答案::

@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 {

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

    public class Two implements Callable {

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

    public class Three implements Callable {

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

    /**
     * @See java.util.concurrent.Future.get() doc
     *      

* 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并发.



4> 小智..:
public class ThreadEvent {

    private final Object lock = new Object();

    public void signal() {
        synchronized (lock) {
            lock.notify();
        }
    }

    public void await() throws InterruptedException {
        synchronized (lock) {
            lock.wait();
        }
    }
}

像这样使用这个类:

创建一个ThreadEvent:

ThreadEvent resultsReady = new ThreadEvent();

在方法中,这是等待结果:

resultsReady.await();

在创建所有结果后创建结果的方法中:

resultsReady.signal();

编辑:

(很抱歉编辑这篇文章,但这段代码的竞争状况非常糟糕,我没有足够的声誉来评论)

如果您100%确定在await()之后调用signal(),则只能使用此方法.这是您无法使用Java对象(如Windows事件)的一个重要原因.

如果代码按此顺序运行:

Thread 1: resultsReady.signal();
Thread 2: resultsReady.await();

然后线程2将永远等待.这是因为Object.notify()只唤醒当前正在运行的线程之一.稍后等待的线程不会被唤醒.这与我期望事件工作的方式非常不同,在事件发出信号之前,a)等待或b)显式重置.

注意:大多数情况下,您应该使用notifyAll(),但这与上面的"永远等待"问题无关.



5> WMR..:

尝试从包中提取CountDownLatch类java.util.concurrent,它提供更高级别的同步机制,远比任何低级别的东西都更不容易出错.



6> kgiannakakis..:

您可以使用两个线程之间共享的Exchanger对象来执行此操作:

private Exchanger myDataExchanger = new Exchanger();

// Wait for thread's output
String data;
try {
  data = myDataExchanger.exchange("");
} catch (InterruptedException e1) {
  // Handle Exceptions
}

在第二个帖子中:

try {
    myDataExchanger.exchange(data)
} catch (InterruptedException e) {

}

正如其他人所说,不要采取这种轻松的,只是复制粘贴代码.先做一些阅读.



7> Maher Abuthr..:

很多正确的答案,但没有一个简单的例子..这是一个简单而简单的方法如何使用CountDownLatch:

//inside your currentThread.. lets call it Thread_Main
//1
final CountDownLatch latch = new CountDownLatch(1);

//2
// launch thread#2
new Thread(new Runnable() {
    @Override
    public void run() {
        //4
        //do your logic here in thread#2

        //then release the lock
        //5
        latch.countDown();
    }
}).start();

try {
    //3 this method will block the thread of latch untill its released later from thread#2
    latch.await();
} catch (InterruptedException e) {
    e.printStackTrace();
}

//6
// You reach here after  latch.countDown() is called from thread#2

推荐阅读
赛亚兔备_393
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有