农行一面:Java如何保证线程T1,T2,T3 顺序执行?

在Java中,保证多个线程按特定顺序执行的核心是通过线程同步机制控制执行时序。以下是几种实现线程顺序执行的常见方法,附代码示例和适用场景分析:


1. 使用 Thread.join():最简单直观

通过主线程依次启动并等待前一线程完成:

public class JoinDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> System.out.println("T1"));
        Thread t2 = new Thread(() -> System.out.println("T2"));
        Thread t3 = new Thread(() -> System.out.println("T3"));

        t1.start();
        t1.join();  // 主线程等待T1结束
        t2.start();
        t2.join();  // 主线程等待T2结束
        t3.start();
    }
}

优点:实现简单,无需复杂同步。
缺点:主线程阻塞,无法并行执行其他任务。


2. 单线程线程池:任务队列保证顺序

利用单线程池的FIFO特性顺序执行任务:

ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(() -> System.out.println("T1"));
executor.submit(() -> System.out.println("T2"));
executor.submit(() -> System.out.println("T3"));
executor.shutdown();

优点:代码简洁,天然有序,自动管理线程生命周期。
缺点:非真正多线程,任务串行执行。


3. CompletableFuture 链式调用:异步编排

通过链式调用实现任务依赖:

CompletableFuture
    .runAsync(() -> System.out.println("T1"))
    .thenRun(() -> System.out.println("T2"))
    .thenRun(() -> System.out.println("T3"))
    .join();  // 等待所有任务完成

优点:异步非阻塞,可扩展复杂依赖。
缺点:依赖线程池配置,需理解异步编程模型。


4. 使用 CountDownLatch:精准控制

通过计数器协调线程执行顺序:

CountDownLatch latch1 = new CountDownLatch(1);
CountDownLatch latch2 = new CountDownLatch(1);

new Thread(() -> {
    System.out.println("T1");
    latch1.countDown();
}).start();

new Thread(() -> {
    try {
        latch1.await();  // 等待T1完成
        System.out.println("T2");
        latch2.countDown();
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
}).start();

new Thread(() -> {
    try {
        latch2.await();  // 等待T2完成
        System.out.println("T3");
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
}).start();

优点:灵活控制复杂依赖,支持多线程协作。
缺点:代码较复杂,需管理多个同步对象。


5. 锁与条件变量(Lock + Condition

通过条件唤醒机制实现顺序控制:

Lock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
AtomicInteger flag = new AtomicInteger(1);

new Thread(() -> {
    lock.lock();
    try {
        while (flag.get() != 1) condition1.await();
        System.out.println("T1");
        flag.set(2);
        condition2.signal();
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    } finally {
        lock.unlock();
    }
}).start();

// T2、T3类似,通过判断flag和condition控制顺序

优点:底层控制能力强,适合复杂同步逻辑。
缺点:代码冗余,易出错,需处理锁的释放。


总结与选择建议

  • 简单场景:优先选Thread.join()或单线程池。
  • 异步任务编排:使用CompletableFuture
  • 复杂协作CountDownLatchCyclicBarrier
  • 精准控制:锁与条件变量。

注意:多线程顺序执行通常与并发设计的初衷(提升效率)相悖,需确保业务场景确实需要顺序性,避免不必要的性能损失。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Debug Your Career

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值