Master Thread Sequencing in Java: 8 Proven Techniques

This article explains why thread execution order is nondeterministic and presents eight Java techniques—join, single‑thread executor, CountDownLatch, CyclicBarrier, Semaphore, synchronized with wait/notify, and Lock with Condition—to reliably enforce sequential execution, complete with clear code examples for each method.

Xuanwu Backend Tech Stack
Xuanwu Backend Tech Stack
Xuanwu Backend Tech Stack
Master Thread Sequencing in Java: 8 Proven Techniques

In interviews, thread execution order is unpredictable because the CPU allocates time slices without coordination.

To enforce sequential execution, several Java mechanisms are presented:

Thread sequential execution

Thread sequential execution means multiple threads run in a defined order rather than concurrently, which is essential when tasks depend on each other.

join() method

The join() method blocks the current thread until the target thread finishes, providing the simplest way to enforce order.

public class ThreadJoinTest {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> System.out.println("线程1执行"));
        Thread t2 = new Thread(() -> System.out.println("线程2执行"));
        Thread t3 = new Thread(() -> System.out.println("线程3执行"));

        t1.start();
        t1.join();   // wait for t1
        t2.start();
        t2.join();   // wait for t2
        t3.start();
        t3.join();   // wait for t3
    }
}

Executors.newSingleThreadExecutor

Creates a single‑thread executor that guarantees tasks are run one after another.

public class NewSingleThreadExecutorTest {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        executor.submit(() -> System.out.println("线程1执行"));
        executor.submit(() -> System.out.println("线程2执行"));
        executor.submit(() -> System.out.println("线程3执行"));
        executor.shutdown();
    }
}

CountDownLatch

Uses a countdown latch to make later threads wait until earlier ones signal completion.

public class CountDownLatchTest {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch cdl1 = new CountDownLatch(1);
        CountDownLatch cdl2 = new CountDownLatch(1);
        Thread t1 = new Thread(() -> {
            System.out.println("线程1执行");
            try { Thread.sleep(1000); } catch (InterruptedException e) {}
            cdl1.countDown();
        });
        Thread t2 = new Thread(() -> {
            try { cdl1.await(); } catch (InterruptedException e) {}
            System.out.println("线程2执行");
            try { Thread.sleep(2000); } catch (InterruptedException e) {}
            cdl2.countDown();
        });
        Thread t3 = new Thread(() -> {
            try { cdl2.await(); } catch (InterruptedException e) {}
            System.out.println("线程3执行");
        });
        t1.start(); t2.start(); t3.start();
        t2.join(); t3.join(); t1.join();
    }
}

CyclicBarrier

Synchronizes groups of threads at barrier points so they proceed in a defined order.

public class CyclicBarrierTest {
    public static void main(String[] args) throws InterruptedException {
        CyclicBarrier barrier1 = new CyclicBarrier(2);
        CyclicBarrier barrier2 = new CyclicBarrier(2);
        Thread t1 = new Thread(() -> {
            System.out.println("线程1执行");
            Thread.sleep(1000);
            barrier1.await();
        });
        Thread t2 = new Thread(() -> {
            barrier1.await();
            System.out.println("线程2执行");
            Thread.sleep(2000);
            barrier2.await();
        });
        Thread t3 = new Thread(() -> {
            barrier2.await();
            System.out.println("线程3执行");
        });
        t1.start(); t2.start(); t3.start();
        t2.join(); t1.join(); t3.join();
    }
}

Semaphore

Controls permits to let threads acquire permission in a specific sequence.

public class SemaphoreTest {
    public static void main(String[] args) throws InterruptedException {
        Semaphore s1 = new Semaphore(0);
        Semaphore s2 = new Semaphore(0);
        Thread t1 = new Thread(() -> {
            System.out.println("线程1开始执行");
            Thread.sleep(2000);
            System.out.println("线程1执行完毕");
            s1.release();
        });
        Thread t2 = new Thread(() -> {
            s1.acquire();
            System.out.println("线程2开始执行");
            Thread.sleep(1000);
            System.out.println("线程2执行完毕");
            s2.release();
        });
        Thread t3 = new Thread(() -> {
            s2.acquire();
            System.out.println("线程3开始执行");
            Thread.sleep(1000);
            System.out.println("线程3执行完毕");
        });
        t1.start(); t2.start(); t3.start();
        t2.join(); t1.join(); t3.join();
    }
}

synchronized + wait()/notify()

Combines a monitor lock with wait() and notifyAll() to enforce turn‑based execution.

public class SynchronizedTest {
    private static final Object lock = new Object();
    private static int turn = 1;
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new Task(1));
        Thread t2 = new Thread(new Task(2));
        Thread t3 = new Thread(new Task(3));
        t1.start(); t2.start(); t3.start();
        t1.join(); t2.join(); t3.join();
    }
    static class Task implements Runnable {
        private final int id;
        Task(int id) { this.id = id; }
        public void run() {
            synchronized (lock) {
                while (turn != id) {
                    lock.wait();
                }
                executeTask(id);
                turn++;
                lock.notifyAll();
            }
        }
        private void executeTask(int id) {
            switch (id) {
                case 1: System.out.println("Thread 1 正在执行任务A"); break;
                case 2: System.out.println("Thread 2 正在执行任务B"); break;
                case 3: System.out.println("Thread 3 正在执行任务C"); break;
                default: System.out.println("其他任务");
            }
        }
    }
}

Lock + Condition

Uses a ReentrantLock with multiple Condition objects to signal the next thread in the sequence.

public class LockTest {
    private static final Lock lock = new ReentrantLock();
    private static final Condition c1 = lock.newCondition();
    private static final Condition c2 = lock.newCondition();
    private static final Condition c3 = lock.newCondition();
    private static int turn = 1;
    public static void main(String[] args) {
        Thread t1 = new Thread(new Task(1, c1, c2));
        Thread t2 = new Thread(new Task(2, c2, c3));
        Thread t3 = new Thread(new Task(3, c3, c1));
        t1.start(); t2.start(); t3.start();
    }
    static class Task implements Runnable {
        private final int id;
        private final Condition cur, next;
        Task(int id, Condition cur, Condition next) { this.id=id; this.cur=cur; this.next=next; }
        public void run() {
            lock.lock();
            try {
                while (turn != id) cur.await();
                executeTask(id);
                turn++;
                next.signal();
            } finally { lock.unlock(); }
        }
        private void executeTask(int id) {
            // similar switch as above
        }
    }
}

These eight approaches give interview candidates practical tools to guarantee ordered thread execution in Java.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaconcurrencythreadSemaphoreLockExecutorServiceCountDownLatch
Xuanwu Backend Tech Stack
Written by

Xuanwu Backend Tech Stack

Primarily covers fundamental Java concepts, mainstream frameworks, deep dives into underlying principles, and JVM internals.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.