5/18/2007

When to join threads

Let's say I need to spawn multiple threads to do the work, and continue to the next step only after all of them complete. I will need to tell the main thread to wait. The key point is to use Thread.join() method. For example,

package foo;
import java.util.Vector;
public class ThreadTest {
private Vector<String> threadNames = new Vector<String>();
public static void main(String[] args) {
ThreadTest test = new ThreadTest();
test.threadTest(Integer.parseInt(args[0]));
System.out.println(test.threadNames);
}
private void threadTest(int numOfThreads) {
Thread[] threads = new Thread[numOfThreads];
for (int i = 0; i < threads.length; i++) {
threads[i] = new foo.ThreadTest.MyThread();
threads[i].start();
}
for (int i = 0; i < threads.length; i++) {
try {
threads[i].join();
} catch (InterruptedException ignore) {}
}
}
class MyThread extends Thread {
public void run() {
for (int i = 0; i < 1000000; i++) {
i = i + 0;
}
threadNames.add(getName());
}
}
}
The output when running this program with 10 threads:
[Thread-1, Thread-3, Thread-0, Thread-5, Thread-7, Thread-6, Thread-9, Thread-2, Thread-8, Thread-4]
The order in which the threads are executed is random, which is expected.

Also note that we use two for-loops, the first to create and start each thread, and the second loop to join each thread. If each thread is joined right after start, the effect is these threads are executed sequentially, without the desired concurrency. For example, the following code snippet results in serial execution:
// The following is NOT concurrent:
//
private void threadTest(int numOfThreads) {
Thread[] threads = new Thread[numOfThreads];
for (int i = 0; i < threads.length; i++) {
threads[i] = new foo.ThreadTest.MyThread();
threads[i].start();
try {
threads[i].join();
} catch (InterruptedException ignore) {
}
}
}
Output:

[Thread-0, Thread-1, Thread-2, Thread-3, Thread-4, Thread-5, Thread-6, Thread-7, Thread-8, Thread-9]
If we don't use any join at all, threadNames, when printed, may be empty, or partially filled, since the main thread will just move on when it gets the chance. The main thread will still wait, at the very last step, for all threads to complete, before exiting the JVM. The output for running 10 threads may be:
[Thread-0, Thread-1, Thread-2, Thread-3]
The following is a general-purpose code skeleton for running concurrency test using anonymous Runnable inner-class:

Thread[] threads = new Thread[numOfThreads];
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(new Runnable() {
public void run() {
System.out.println("xxx");
}
});
threads[i].start();
}
for (int i = 0; i < threads.length; i++) {
try {
threads[i].join();
} catch (InterruptedException e) {
}
}
Another version using java.util.concurrent.CountDownLatch: When to join threads with CountDownLatch

Tags: ,

37 comments:

Lakshitha Ranasinghe said...

Thanks for the code snippet about thread join. It helped me.
Regards,
Lakshitha Ranasinghe

anirban said...

Thanks dude.It helped me a lot.

Regards,
Anirban Gangopadhyay

Anonymous said...

Hi buddy,
In your code you have created the threads[i] as instance to which your are assigning new foo.Threadset.Mythread().How??? can you explain this to me....

javahowto said...

MyThread is just an inner class inside ThreadTest class. The inner class also access a vector field from the outer class.

I could've written MyThread as a separate class and should work the same way. Of course, then the vector field will need to be publicly accessible.

Anonymous said...

It really helped

Anonymous said...

Wouldn't be better to use a CyclicBarrier object?

Anonymous said...

Wouldn't it be better to use a CyclicBarrier object?

Anonymous said...

Thanks a lot. It was exactly what I wanted to know.

Anonymous said...

Do NOT use CyclicBarrier - ever - unless you understand exactly the performance implications of notifyAll and the underlying thread thrashing that results from it. If you have many threads all updating the SAME object, CyclicBarrier would be a disaster. Better to single file them all using join().

priti said...

Thanks for the code yaar.. i searched lot for joining of threads n finally ur code helped me..
Regards,
Priti..

Anonymous said...

Thank you very much for the simple yet effective description about thread join... Keep it up!!!

Tong Wang said...

Crystal clear. Good job

Nrj said...

Good one, thanks.

Steffen Bartsch said...

One question: isn't it a risk to join the thread only after having it already started? The runnning thread could have been finished at that time.

Anonymous said...

Very Nice Article..

Joseph

Nishant said...

thanks dude ... this code is helpful to me... i was exactly looking for the same code...thanks

Galian said...

thank you for the code. But I have one question:

if you are creating thread in loop, for example 0-iteration, thread created, called join, after this point, as I understand calling thread should be blocked, and we will not created thread on iteration 1? So how can it be, that you are able to step next instruction after join?

Hari said...

Thanks for the code. great time saver!!!

Muhammad Azeem said...

hi good code is their also

see

http://java.pakcarid.com/Cpp.aspx?sub=230&sls=24&topid=32

Sabir Hussain said...

Just wanted to add some clarification.

Thread t1 = new Thread();

t1.join() means "wait for this thread to die", now the question is who will wait for whom.

In simple terms it means, every java program starts with a main thread, so here this main thread will be blocked or will wait till thread t1 life cycle ends.
Or any statement next to the t1.join() will be executed only after thread t1 dies.

So suppose you want that your 2 or more threads should do some important work and main thread should wait until all your threads complete there life cycle, in that case use join().

never write code like this:

Suppose you have threads t1, t2 and t3

t1.start();
t1.join();
t2.start();
t2.join();
t3.start();
t3.join();

In the above case spawning 3 threads is of no use, as t2 will start only after t1 dies, t3 will start only after t2 dies.

Instead code like this:

t1.start();
t2.start();
t3.start();
t1.join();
t2.join();
t3.join();

enjoy!
Sabir

Anonymous said...

have you any idea how to implement join function ??

Eriglen Gani said...

Thanks! It was useful

The Saildier said...

Exactly what I needed. You just salvaged my thesis.

Equipo 7 said...

Yeah...It's useful .

Thanks!
Regards!

Tamir Sasson said...

Thank you very much, it is very clear now

Anonymous said...

Hi,
I have only one objection to this example:
You expect that the threads finish working in the order you use join in:
for example if the third thread is finished but the first is not the third thread will have to wait for the first to be finished because you call the method join in the order
thread0 thread1 until thread 9.

Can you reply to me at this address:alexdraganesc@gmail.com

Abhishek said...

Hi, we can not put t1.join immediately after t1.start ..you need to start all and then only do join. else main thread waits for t1 to finish first.

Anonymous said...

@alexdraganesc
You don't understand that it is the main thread which is waiting for ALL child threads to finish! The child-threads aren't "waiting for each other"! Only the main thread (the one which launched the other threads) is waiting.
Therefore it doesn't matter which child thread finishes first, second, third, etc. If a child thread is already finished, join() on that thread just returns without additional waiting.

Dimitris said...

Hello,
In this example, what would be a good way to have on the one hand Concurrency on the other reversed order of the execution ?
Can two threads play at the same time but finish in some order ?

Thank you in advance.

Anonymous said...

good post ...

Anonymous said...

Thanks for the post:)

Anonymous said...

Thanks.

Anonymous said...

Thanks! Very useful!

Anonymous said...

Good one actually..if you dont feel so .....try to understand it again ..
:)

Moh Abdullah said...

Simple and clear, Thanks.

java67 said...

In order to join threads in Java, order is very important. Here is a good exercise to learn how to join threads in Java

Anonymous said...

Thanks buddy, It has helped me to learn about threads.