I'm trying to learn about threads and I do not understand the join()
method.
I have a Thread (ThreadAdd.java) which adds 1 to a static int.
public class ThreadAdd extends Thread{
public static int count;
@Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(ThreadAdd.class.getName()).log(Level.SEVERE, null, ex);
}
ThreadAdd.count++;
}
}
In my main
method I launch 2 threads :
public static void main(String[] args) throws InterruptedException {
ThreadAdd s1 = new ThreadAdd();
ThreadAdd s2 = new ThreadAdd();
s1.start();s2.start();
s1.join();
s2.join();
System.out.println(ThreadAdd.count);
}
I do not understand why most of the time the result is 2 but sometimes it returns 1.
join() Method. Waits for this thread to die. When we invoke the join() method on a thread, the calling thread goes into a waiting state.
Join is a synchronization method that blocks the calling thread (that is, the thread that calls the method) until the thread whose Join method is called has completed. Use this method to ensure that a thread has been terminated. The caller will block indefinitely if the thread does not terminate.
Both wait() and join() can be interrupted by calling interrupt() method in Java. Both wait() and join() are a non-static method. Both wait() and join() are overloaded in Java. wait() and join() which without timeout as well as accepts a timeout parameter.
wait() method is a part of java. lang. Object class. When wait() method is called, the calling thread stops its execution until notify() or notifyAll() method is invoked by some other Thread.
The reason why you sometimes see 1
is not because join()
fails to wait for the thread to finish, but because both threads tried to modify the value concurrently. When this happens, you may see unexpected results: for example, when both threads try to increment count
which is zero, they both could read zero, then add 1 to it, and store the result. Both of them will store the same exact result, i.e. 1, so that's what you are going to see no matter how long you wait.
To fix this problem, add synchronized
around the increment, or use AtomicInteger
:
public static AtomicInteger count = new AtomicInteger(0);
@Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(ThreadAdd.class.getName()).log(Level.SEVERE, null, ex);
}
ThreadAdd.count.incrementAndGet();
}
The join
method is not the real issue here. The problem is that your counter is not prepared for interthread synchronization, which may lead to each thread observing a different value in count
.
It is highly recommended that you study some topics of concurrent programming, including how it is handled in Java.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With