Div*_*ero 103 java parallel-processing multithreading wait
简单地等待所有线程进程完成的方法是什么?例如,假设我有:
public class DoSomethingInAThread implements Runnable{
public static void main(String[] args) {
for (int n=0; n<1000; n++) {
Thread t = new Thread(new DoSomethingInAThread());
t.start();
}
// wait for all threads' run() methods to complete before continuing
}
public void run() {
// do something here
}
}
Run Code Online (Sandbox Code Playgroud)
我如何改变这一点,以便main()
方法在注释处暂停,直到所有线程的run()
方法都退出?谢谢!
Mar*_*wis 157
您将所有线程放在一个数组中,启动它们,然后循环
for(i = 0; i < threads.length; i++)
threads[i].join();
Run Code Online (Sandbox Code Playgroud)
每个连接将阻塞,直到相应的线程完成.线程可以以与加入它们不同的顺序完成,但这不是问题:当循环退出时,所有线程都完成.
Ada*_*kin 37
一种方法是做一个List
的Thread
S,创建和启动每个线程,而将其添加到列表中.一旦启动所有内容,循环回列表并调用join()
每个列表.线程完成执行的顺序并不重要,您需要知道的是,当第二个循环完成执行时,每个线程都将完成.
更好的方法是使用ExecutorService及其相关方法:
List<Callable> callables = ... // assemble list of Callables here
// Like Runnable but can return a value
ExecutorService execSvc = Executors.newCachedThreadPool();
List<Future<?>> results = execSvc.invokeAll(callables);
// Note: You may not care about the return values, in which case don't
// bother saving them
Run Code Online (Sandbox Code Playgroud)
使用ExecutorService(以及来自Java 5的并发实用程序的所有新东西)非常灵活,上面的示例几乎没有表面上的划痕.
jt.*_*jt. 24
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class DoSomethingInAThread implements Runnable
{
public static void main(String[] args) throws ExecutionException, InterruptedException
{
//limit the number of actual threads
int poolSize = 10;
ExecutorService service = Executors.newFixedThreadPool(poolSize);
List<Future<Runnable>> futures = new ArrayList<Future<Runnable>>();
for (int n = 0; n < 1000; n++)
{
Future f = service.submit(new DoSomethingInAThread());
futures.add(f);
}
// wait for all tasks to complete before continuing
for (Future<Runnable> f : futures)
{
f.get();
}
//shut down the executor service so that this thread can exit
service.shutdownNow();
}
public void run()
{
// do something here
}
}
Run Code Online (Sandbox Code Playgroud)
而不是join()
旧的API,您可以使用CountDownLatch.我已经修改了您的代码,以满足您的要求.
import java.util.concurrent.*;
class DoSomethingInAThread implements Runnable{
CountDownLatch latch;
public DoSomethingInAThread(CountDownLatch latch){
this.latch = latch;
}
public void run() {
try{
System.out.println("Do some thing");
latch.countDown();
}catch(Exception err){
err.printStackTrace();
}
}
}
public class CountDownLatchDemo {
public static void main(String[] args) {
try{
CountDownLatch latch = new CountDownLatch(1000);
for (int n=0; n<1000; n++) {
Thread t = new Thread(new DoSomethingInAThread(latch));
t.start();
}
latch.await();
System.out.println("In Main thread after completion of 1000 threads");
}catch(Exception err){
err.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
说明:
CountDownLatch
已根据您的要求初始化给定计数1000.
每个工作线程DoSomethingInAThread
将递减CountDownLatch
,它已在构造函数中传递.
主线程CountDownLatchDemo
await()
直到计数变为零.一旦计数变为零,您将获得输出线以下.
In Main thread after completion of 1000 threads
Run Code Online (Sandbox Code Playgroud)更多信息来自oracle文档页面
public void await()
throws InterruptedException
Run Code Online (Sandbox Code Playgroud)
除非线程被中断,否则导致当前线程等待锁存器倒计数到零.
有关其他选项,请参阅相关的SE问题:
根据您的需要,您可能还想查看 java.util.concurrent 包中的 CountDownLatch 和 CyclicBarrier 类。如果您希望线程相互等待,或者希望对线程执行方式进行更细粒度的控制(例如,在其内部执行中等待另一个线程设置某种状态),那么它们会很有用。您还可以使用 CountDownLatch 向所有线程发出同时启动的信号,而不是在迭代循环时逐个启动它们。标准 API 文档有一个这样的示例,并使用另一个 CountDownLatch 来等待所有线程完成执行。
正如Martin K所说, java.util.concurrent.CountDownLatch
似乎是一个更好的解决方案.只需添加相同的示例
public class CountDownLatchDemo
{
public static void main (String[] args)
{
int noOfThreads = 5;
// Declare the count down latch based on the number of threads you need
// to wait on
final CountDownLatch executionCompleted = new CountDownLatch(noOfThreads);
for (int i = 0; i < noOfThreads; i++)
{
new Thread()
{
@Override
public void run ()
{
System.out.println("I am executed by :" + Thread.currentThread().getName());
try
{
// Dummy sleep
Thread.sleep(3000);
// One thread has completed its job
executionCompleted.countDown();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
}
try
{
// Wait till the count down latch opens.In the given case till five
// times countDown method is invoked
executionCompleted.await();
System.out.println("All over");
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)