Ordered Thread Execution in Java: join, CountDownLatch, Single Thread Pool, and CompletableFuture
This article explains how to enforce a specific execution order among three Java threads—first thread 1, then thread 2, and finally thread 3—using four techniques: the join method, CountDownLatch, a single‑thread executor, and CompletableFuture, each illustrated with complete code examples.
When multiple threads need to run in a strict sequence (thread 1 → thread 2 → thread 3), the default scheduler may interleave them, so explicit coordination is required.
One simple way is to use Thread.join(), which makes a thread wait until another finishes. The following example creates three threads where each thread receives the previous thread and calls join() before printing its name.
public class ThreadLoopOne {
public static void main(String[] args) {
Thread t1 = new Thread(new Work(null));
Thread t2 = new Thread(new Work(t1));
Thread t3 = new Thread(new Work(t2));
t1.start();
t2.start();
t3.start();
}
static class Work implements Runnable {
private Thread beforeThread;
public Work(Thread beforeThread) {
this.beforeThread = beforeThread;
}
@Override
public void run() {
// 如果有线程,就 join 进来,没有的话就直接输出
if (beforeThread != null) {
try {
beforeThread.join();
System.out.println("thread start : " + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println("thread start : " + Thread.currentThread().getName());
}
}
}
}Another approach is to use CountDownLatch as a signaling mechanism. Each thread waits on a latch that is counted down by the preceding thread, ensuring the desired order.
public class ThreadLoopTwo {
public static void main(String[] args) {
// 设置线程 1 的信号量为 0
CountDownLatch cOne = new CountDownLatch(0);
// 设置线程 2 的信号量为 1
CountDownLatch cTwo = new CountDownLatch(1);
// 设置线程 3 的信号量为 1
CountDownLatch cThree = new CountDownLatch(1);
// 因为 cOne 为 0 ,故 t1 可以直接执行
Thread t1 = new Thread(new Work(cOne,cTwo));
// 线程 t1 执行完毕之后,此时的 cTwo 为 0 , t2 开始执行
Thread t2 = new Thread(new Work(cTwo,cThree));
// 线程 t2 执行完毕,此时 cThree 为 0 , t3 开始执行
Thread t3 = new Thread(new Work(cThree,cThree));
t1.start();
t2.start();
t3.start();
}
static class Work implements Runnable {
CountDownLatch cOne;
CountDownLatch cTwo;
public Work(CountDownLatch cOne, CountDownLatch cTwo) {
super();
this.cOne = cOne;
this.cTwo = cTwo;
}
@Override
public void run() {
try {
// 当前一个线程信号量为 0 时,才执行
cOne.await();
System.out.println("thread start : " + Thread.currentThread().getName());
// 后一个线程信号量减 1
cTwo.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}Using a single‑thread executor also guarantees order because tasks are executed one after another in the thread pool.
public class ThreadLoopThree {
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("thread start : " + Thread.currentThread().getName() + " run one");
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("thread start : " + Thread.currentThread().getName() + " run two");
}
});
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("thread start : " + Thread.currentThread().getName() + " run three");
}
});
ExecutorService executor = Executors.newSingleThreadExecutor();
// 将线程依次加入到线程池中
executor.submit(t1);
executor.submit(t2);
executor.submit(t3);
// 及时将线程池关闭
executor.shutdown();
}
}Finally, CompletableFuture can chain asynchronous actions, starting each thread after the previous one has been launched.
public class ThreadLoopFour {
public static void main(String[] args) {
Thread t1 = new Thread(new Work());
Thread t2 = new Thread(new Work());
Thread t3 = new Thread(new Work());
CompletableFuture.runAsync(()-> t1.start())
.thenRun(()->t2.start())
.thenRun(()->t3.start());
}
static class Work implements Runnable {
@Override
public void run() {
System.out.println("thread start : " + Thread.currentThread().getName());
}
}
}Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Full-Stack Internet Architecture
Introducing full-stack Internet architecture technologies centered on Java
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
