I have one main thread that starts 10 other threads. I want that the main thread will be finished only after all other threads stopped. So should I call join() on other 10 threads before starting or after starting them. For instance:
// in the main() method of Main thread
Thread [] threads = new Thread[10];
for(int i = 0; i < 10; i++) 开发者_JS百科{
// 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
- So as in the above example, should i call join() before start() or after start().
- Will the control returns to line no. 9 only after all the threads have finished.
- When the run method of any thread has been executed, then will that thread die or remain alive. If it will, the how to die all the threads when their run method has finished means when the control returns to line no. 9
Calling join()
on a thread only makes sense after the thread is started. The caller of join()
will stop and wait until the other thread finishes what it's doing. So you may want to do this:
// 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");
I recommend against using the low-level Thread constructs like join(), and instead using the higher-level stuff in java.util.concurrent
, like CyclicBarrier:
A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point. CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other. The barrier is called cyclic because it can be re-used after the waiting threads are released.
The usage is much more obvious that Thread.join()
, and much less prone to weird bugs.
Instead of writing your own code, you code use a ThreadPoolExecutor to do what you need:
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
}
This way, you could easily use less threads to do more tasks if you wish - without changing the code.
you should first start all the thread, then start joining them. Join will return direct if called before the thread is start.
Case can be that you want to join group of threads. See javadoc for
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);
}
}
For trivial scenarios (one thread), Thread.join() is enough.
精彩评论