views:

271

answers:

4

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++) {
    // 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
  1. So as in the above example, should i call join() before start() or after start().
  2. Will the control returns to line no. 9 only after all the threads have finished.
  3. 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
+6  A: 

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");
Greg Hewgill
Can I insert the "threads[i].join()" statement within the first for loop after the "threads.start()" statement.
Yatendra Goel
You can, but then your second thread won't start until the first one finishes. With my above code, all 10 threads will be able to run in parallel until they all stop.
Greg Hewgill
+1  A: 

you should first start all the thread, then start joining them. Join will return direct if called before the thread is start.

Salandur
+6  A: 

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.

skaffman
+3  A: 

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.

sfussenegger
can you answer my other question at http://stackoverflow.com/questions/1611862/how-to-stop-threads-in-java
Yatendra Goel
You'll want to put that `ThreadPoolExecutor` creation statement inside the try block, though
skaffman
For what reason would you put it inside the try block?
sfussenegger
@Yatendra I've nothing to add to the question you mentioned - it's already answered.
sfussenegger
@sfussenegger: Because executor.execute() can throw an exception, and you'd be left with an un-shutdown ThreadPool.
skaffman
@skaffman: Ah, so the .execute() should go inside the try block, not the creation. But execute shouldn't throw an exception as well, as the ThreadPoolExecutor is constructed with an unlimited queue - hence no RejectedExecutionException to expect.
sfussenegger