我有一个主线程启动10个其他线程。我希望只有在所有其他线程停止后才能完成主线程。所以我应该在开始之前或之后调用其他10个线程上的join()。例如:
// in the main() method of Main thread
Thread [] threads = new Thread[10];
for(int i = 0; i < 10; i++) {
// ParserThread() is a runnable thread
threads[i] = new Thread(new ParserThread());
threads[i].join();
threads[i].start();
}
System.out.println("All threads have been finished"); // line no. 9
答案 0 :(得分:7)
在线程启动后,只在线程上调用join()
才有意义。 join()
的调用者将停止并等待另一个线程完成它正在执行的操作。所以你可能想这样做:
// in the main() method of Main thread
Thread [] threads = new Thread[10];
for(int i = 0; i < 10; i++) {
// ParserThread() is a runnable thread
threads[i] = new Thread(new ParserThread());
threads[i].start();
}
System.out.println("All threads have been started");
for(int i = 0; i < 10; i++) {
threads[i].join();
}
System.out.println("All threads have been finished");
答案 1 :(得分:6)
我建议不要使用像join()这样的低级Thread构造,而是使用java.util.concurrent
中的更高级别的东西,比如CyclicBarrier:
允许a的同步辅助 一组线程都等待每一个 另一个达到共同的障碍点。 CyclicBarriers在程序中很有用 涉及固定规模的党 必须偶尔等待的线程 对于彼此。屏障被称为 循环因为它可以在之后重复使用 等待线程被释放。
Thread.join()
和很多不太容易出现奇怪错误的用法更为明显。
答案 2 :(得分:5)
您不需要编写自己的代码,而是使用ThreadPoolExecutor来执行您需要的操作:
ThreadPoolExecutor executor = new ThreadPoolExecutor(0, 10, 2, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
for (int i = 0; i < 10; i++)
executor.execute(new ParserThread());
try {
executor.shutdown();
executor.awaitTermination(10, TimeUnit.MINUTES);
} catch (final InterruptedException e) {
// handle
}
通过这种方式,您可以轻松地使用更少的线程来执行更多任务 - 无需更改代码。
答案 3 :(得分:1)
首先应该启动所有线程,然后开始加入它们。如果在线程开始之前调用,Join将直接返回。
答案 4 :(得分:0)
案例可以是您想要加入线程组。请参阅javadoc
http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorCompletionService.html
void solve(Executor e,
Collection<Callable<Result>> solvers)
throws InterruptedException, ExecutionException {
CompletionService<Result> ecs
= new ExecutorCompletionService<Result>(e);
for (Callable<Result> s : solvers)
ecs.submit(s);
int n = solvers.size();
for (int i = 0; i < n; ++i) {
Result r = ecs.take().get();
if (r != null)
use(r);
}
}
对于琐碎的场景(一个线程),Thread.join()就足够了。