Java 如何等待多个线程完成?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1252190/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to wait for a number of threads to complete?
提问by DivideByHero
What is a way to simply wait for all threaded process to finish? For example, let's say I have:
什么是简单地等待所有线程进程完成的方法?例如,假设我有:
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
}
}
How do I alter this so the main()
method pauses at the comment until all threads' run()
methods exit? Thanks!
如何更改此main()
方法以便该方法在注释处暂停,直到所有线程的run()
方法退出?谢谢!
采纳答案by Martin v. L?wis
You put all threads in an array, start them all, and then have a loop
你把所有线程放在一个数组中,启动它们,然后有一个循环
for(i = 0; i < threads.length; i++)
threads[i].join();
Each join will block until the respective thread has completed. Threads may complete in a different order than you joining them, but that's not a problem: when the loop exits, all threads are completed.
每个连接都会阻塞,直到相应的线程完成。线程的完成顺序可能与您加入它们的顺序不同,但这不是问题:当循环退出时,所有线程都已完成。
回答by Martin K.
You can do it with the Object "ThreadGroup" and its parameter activeCount:
回答by David
If you make a list of the threads, you can loop through them and .join() against each, and your loop will finish when all the threads have. I haven't tried it though.
如果您列出线程,您可以遍历它们并对每个线程执行 .join() ,当所有线程都完成时,您的循环将结束。不过我没试过。
http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#join()
http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#join()
回答by Adam Batkin
One way would be to make a List
of Thread
s, create and launch each thread, while adding it to the list. Once everything is launched, loop back through the list and call join()
on each one. It doesn't matter what order the threads finish executing in, all you need to know is that by the time that second loop finishes executing, every thread will have completed.
一种方法是做一个List
的Thread
S,创建和启动每个线程,而将其添加到列表中。启动所有内容后,循环返回列表并调用join()
每个列表。线程完成执行的顺序无关紧要,您需要知道的是,当第二个循环完成执行时,每个线程都将完成。
A better approach is to use an ExecutorServiceand its associated methods:
更好的方法是使用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
Using an ExecutorService (and all of the new stuff from Java 5's concurrency utilities) is incredibly flexible, and the above example barely even scratches the surface.
使用 ExecutorService(以及来自 Java 5并发实用程序的所有新东西)非常灵活,上面的例子几乎没有触及表面。
回答by henrik
Avoid the Thread class altogether and instead use the higher abstractions provided in java.util.concurrent
完全避免使用 Thread 类,而是使用 java.util.concurrent 中提供的更高抽象
The ExecutorService class provides the method invokeAllthat seems to do just what you want.
ExecutorService 类提供的方法 invokeAll似乎可以满足您的需求。
回答by Jeff
Depending on your needs, you may also want to check out the classes CountDownLatch and CyclicBarrier in the java.util.concurrent package. They can be useful if you want your threads to wait for each other, or if you want more fine-grained control over the way your threads execute (e.g., waiting in their internal execution for another thread to set some state). You could also use a CountDownLatch to signal all of your threads to start at the same time, instead of starting them one by one as you iterate through your loop. The standard API docs have an example of this, plus using another CountDownLatch to wait for all threads to complete their execution.
根据您的需要,您可能还想查看 java.util.concurrent 包中的 CountDownLatch 和 CyclicBarrier 类。如果您希望线程相互等待,或者希望对线程执行方式进行更细粒度的控制(例如,在它们的内部执行中等待另一个线程设置某些状态),它们会很有用。您还可以使用 CountDownLatch 来通知所有线程同时启动,而不是在循环遍历时一个一个地启动它们。标准 API 文档有一个这样的例子,另外还使用另一个 CountDownLatch 来等待所有线程完成它们的执行。
回答by jt.
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
}
}
回答by optimus0127
Create the thread object inside the first for loop.
在第一个 for 循环内创建线程对象。
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(new Runnable() {
public void run() {
// some code to run in parallel
}
});
threads[i].start();
}
And then so what everyone here is saying.
那么这里的每个人都在说什么。
for(i = 0; i < threads.length; i++)
threads[i].join();
回答by Pablo Cavalieri
Consider using java.util.concurrent.CountDownLatch
. Examples in javadocs
考虑使用java.util.concurrent.CountDownLatch
. javadoc 中的示例
回答by Freaky Thommi
As Martin K suggested java.util.concurrent.CountDownLatch
seems to be a better solution for this. Just adding an example for the same
正如 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();
}
}
}