我正在使用应用程序逻辑线程和数据库访问线程创建Java应用程序.他们都坚持为应用程序的整个生命周期,并都需要在同一时间运行(一个会谈到服务器,一个谈判给用户;当应用程序完全启动,我需要两个人工作).
但是,在启动时,我需要确保最初应用程序线程等待直到db线程准备就绪(当前通过轮询自定义方法确定dbthread.isReady()
).我不介意app线程阻塞,直到db线程准备好.
Thread.join()
看起来不像解决方案 - 数据库线程仅在应用程序关闭时退出.
while (!dbthread.isReady()) {}
有点工作,但空循环消耗了大量的处理器周期.
还有其他想法吗?谢谢.
使用计数器为1 的CountDownLatch.
CountDownLatch latch = new CountDownLatch(1);
现在在app线程中 -
latch.await();
在db线程中,完成后,执行 -
latch.countDown();
我建议您在开始进行多线程的神奇世界之前,先阅读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
包和子包中有很多漂亮的并发类.你真的需要在网上找到材料来了解并发性,或者获得一本好书.
要求::
等待执行下一个线程直到上一个完成.
无论时间消耗如何,下一个线程都必须在前一个线程停止之前才能启动.
它必须简单易用.
答案::
@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并发.
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(),但这与上面的"永远等待"问题无关.
尝试从包中提取CountDownLatch类java.util.concurrent
,它提供更高级别的同步机制,远比任何低级别的东西都更不容易出错.
您可以使用两个线程之间共享的Exchanger对象来执行此操作:
private ExchangermyDataExchanger = 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) { }
正如其他人所说,不要采取这种轻松的,只是复制粘贴代码.先做一些阅读.
很多正确的答案,但没有一个简单的例子..这是一个简单而简单的方法如何使用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