Pis*_*3.0 125 java multithreading
我正在使用应用程序逻辑线程和数据库访问线程创建Java应用程序.他们都坚持为应用程序的整个生命周期,并都需要在同一时间运行(一个会谈到服务器,一个谈判给用户;当应用程序完全启动,我需要两个人工作).
但是,在启动时,我需要确保最初应用程序线程等待直到db线程准备就绪(当前通过轮询自定义方法确定dbthread.isReady()).我不介意app线程阻塞,直到db线程准备好.
Thread.join() 看起来不像解决方案 - 数据库线程仅在应用程序关闭时退出.
while (!dbthread.isReady()) {} 有点工作,但空循环消耗了大量的处理器周期.
还有其他想法吗?谢谢.
pde*_*eva 135
使用计数器为1 的CountDownLatch.
CountDownLatch latch = new CountDownLatch(1);
Run Code Online (Sandbox Code Playgroud)
现在在app线程中 -
latch.await();
Run Code Online (Sandbox Code Playgroud)
在db线程中,完成后,执行 -
latch.countDown();
Run Code Online (Sandbox Code Playgroud)
Her*_*elt 127
我建议您在开始进行多线程的神奇世界之前,先阅读Sun的Java Concurrency等教程.
还有很多好书(google为"Java中的并发编程","实践中的Java并发").
得到你的答案:
在你必须等待的代码中dbThread,你必须有这样的东西:
//do some work
synchronized(objectYouNeedToLockOn){
while (!dbThread.isReady()){
objectYouNeedToLockOn.wait();
}
}
//continue with work after dbThread is ready
Run Code Online (Sandbox Code Playgroud)
在你dbThread的方法中,你需要做这样的事情:
//do db work
synchronized(objectYouNeedToLockOn){
//set ready flag to true (so isReady returns true)
ready = true;
objectYouNeedToLockOn.notifyAll();
}
//end thread run method here
Run Code Online (Sandbox Code Playgroud)
的objectYouNeedToLockOn最好我用这些例子是,你需要从每个线程并发操作的对象,或者你可以创建一个单独的Object用于该目的(我不建议使自己同步的方法):
private final Object lock = new Object();
//now use lock in your synchronized blocks
Run Code Online (Sandbox Code Playgroud)
为了进一步理解:
还有其他(有时是更好的)方法来完成上述操作,例如使用CountdownLatches等.自Java 5以来,java.util.concurrent包和子包中有很多漂亮的并发类.你真的需要在网上找到材料来了解并发性,或者获得一本好书.
Ash*_*Ash 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();
}
}
Run Code Online (Sandbox Code Playgroud)
该程序的输出::
One...
One!!
Two...
Two!!
Three...
Three!!
Run Code Online (Sandbox Code Playgroud)
您可以看到在完成任务之前需要6秒,这比其他线程更大.所以Future.get()等待任务完成.
如果你不使用future.get(),它不会等待完成并执行基于时间的消耗.
祝你好运与Java并发.
小智 8
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
像这样使用这个类:
创建一个ThreadEvent:
ThreadEvent resultsReady = new ThreadEvent();
Run Code Online (Sandbox Code Playgroud)
在方法中,这是等待结果:
resultsReady.await();
Run Code Online (Sandbox Code Playgroud)
在创建所有结果后创建结果的方法中:
resultsReady.signal();
Run Code Online (Sandbox Code Playgroud)
编辑:
(很抱歉编辑这篇文章,但这段代码的竞争状况非常糟糕,我没有足够的声誉来评论)
如果您100%确定在await()之后调用signal(),则只能使用此方法.这是您无法使用Java对象(如Windows事件)的一个重要原因.
如果代码按此顺序运行:
Thread 1: resultsReady.signal();
Thread 2: resultsReady.await();
Run Code Online (Sandbox Code Playgroud)
然后线程2将永远等待.这是因为Object.notify()只唤醒当前正在运行的线程之一.稍后等待的线程不会被唤醒.这与我期望事件工作的方式非常不同,在事件发出信号之前,a)等待或b)显式重置.
注意:大多数情况下,您应该使用notifyAll(),但这与上面的"永远等待"问题无关.
您可以使用两个线程之间共享的Exchanger对象来执行此操作:
private Exchanger<String> myDataExchanger = new Exchanger<String>();
// Wait for thread's output
String data;
try {
data = myDataExchanger.exchange("");
} catch (InterruptedException e1) {
// Handle Exceptions
}
Run Code Online (Sandbox Code Playgroud)
在第二个帖子中:
try {
myDataExchanger.exchange(data)
} catch (InterruptedException e) {
}
Run Code Online (Sandbox Code Playgroud)
正如其他人所说,不要采取这种轻松的,只是复制粘贴代码.先做一些阅读.
很多正确的答案,但没有一个简单的例子..这是一个简单而简单的方法如何使用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
Run Code Online (Sandbox Code Playgroud)