This post would demo how to ensure the thread execution order by using Thread.join or the CountDownLatch.
- Java 1.8
Via the Thread.join method
According to JAVA API document, Thread.join let the current thread to wait for the thread for some time, just as follows:
public final void join(long millis) throws InterruptedException
Waits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever. This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.
And there is a simple join method:
public final void join() throws InterruptedException
Waits for this thread to die.An invocation of this method behaves in exactly the same way as the invocation: join(0)
We would create three threads and let them execute in this order:
- Thread2 starts as soon as thread1 end
- Thread3 starts 1 second after the the thread2 starts
- Main thread would wait all threads done
Create a custom Thread class
Here we create a custom thread class with name and sleeping features as follows:
As you can see, the thread just sleep for 3 seconds and then end.
use the thread.join to control the order of thread execution
Pay attention to thread3.join, if you remove this line of code, the main thread would not wait all threads done.
- thread1 started and sleep 3 seconds
- thread1.join() called, then main thread would wait until thread1 is done
- thread2 start and join(1000), it would wait at most 1 second
- After 1 second, thread3.start called, and thread3.join make the main thread to wait until the thread3 is done
run the code and we got this console output:
The order is just the same as expected.
Now we would have one producer thread and one consumer thread, the consumer must wait for the producer complete its job.
According to the api, CountDownLatch is
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
For the initiation of the CountDownLatch:
A CountDownLatch is initialized with a given count. The await methods block until the current count reaches zero due to invocations of the countDown() method, after which all waiting threads are released and any subsequent invocations of await return immediately. This is a one-shot phenomenon – the count cannot be reset. If you need a version that resets the count, consider using a CyclicBarrier.
CountDownLatch(int count) Constructs a CountDownLatch initialized with the given count.
The countDown method:
countDown() Decrements the count of the latch, releasing all waiting threads if the count reaches zero.
The await method:
await() Causes the current thread to wait until the latch has counted down to zero, unless the thread is interrupted.
The CountDownLatch property
We define a CountDownLatch with only one lock , because there is only one producer thread to wait.
The producer thread
Note the latch.countDown() , this method would decrease the latch ,and notify the waiter.
The consumer thread
We create a consumer thread ,and the key point is as follows:
- in the run() method, we call latch.await() , this would pause the current thread and wait for the countdown to zero.
The consumer and producer threads execution in order
We should notice that:
- we just call the producer and consumer’s start to run all the threads
- At last we call the consumer’s join method to wait for the consumer to complete
Let’s run the code ,and we got this output:
the key points are as follows:
- The producer and consumer threads are started almost simultaneously, but the consumer thread just waiting for the producer thread
- After the producer thread done, the consumer thread start in real
- After all threads done, the main thread ends
Process finished with exit code 0
It’s so easy, do you think so?
You can find detail documents about the springboot and unit testing here: