如何在 Java 中控制多个线程的执行顺序?

在这里插入图片描述

回答

在 Java 中,线程的执行顺序默认由 JVM 和操作系统调度器决定,无法直接保证。但通过特定的同步机制和工具,可以控制多个线程的执行顺序。以下是几种常见方法及其实现原理:

1. 使用 join() 方法
  • 原理Thread.join() 使当前线程等待目标线程完成后继续执行。
  • 适用场景:简单线性顺序。
  • 示例
    public class JoinExample {
        public static void main(String[] args) throws InterruptedException {
            Thread t1 = new Thread(() -> System.out.println("Thread 1"));
            Thread t2 = new Thread(() -> System.out.println("Thread 2"));
            Thread t3 = new Thread(() -> System.out.println("Thread 3"));
    
            t1.start();
            t1.join(); // 等待 t1 完成
            t2.start();
            t2.join(); // 等待 t2 完成
            t3.start();
            t3.join(); // 等待 t3 完成
    
            System.out.println("All threads finished");
        }
    }
    
  • 输出
    Thread 1
    Thread 2
    Thread 3
    All threads finished
    
  • 优点:简单直观。
  • 缺点:只能控制线性依赖,不够灵活。
2. 使用 CountDownLatch
  • 原理:通过计数器协调线程,等待所有前置线程完成。
  • 适用场景:一组线程完成后另一组开始。
  • 示例
    import java.util.concurrent.*;
    
    public class CountDownLatchExample {
        public static void main(String[] args) throws InterruptedException {
            CountDownLatch latch1 = new CountDownLatch(1);
            CountDownLatch latch2 = new CountDownLatch(1);
    
            Thread t1 = new Thread(() -> {
                System.out.println("Thread 1");
                latch1.countDown();
            });
            Thread t2 = new Thread(() -> {
                try {
                    latch1.await();
                    System.out.println("Thread 2");
                    latch2.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            Thread t3 = new Thread(() -> {
                try {
                    latch2.await();
                    System.out.println("Thread 3");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
    
            t1.start();
            t2.start();
            t3.start();
        }
    }
    
  • 输出
    Thread 1
    Thread 2
    Thread 3
    
  • 优点:支持多线程等待一个条件。
  • 缺点:不可重用,需提前规划计数。
3. 使用 CyclicBarrier
  • 原理:多个线程互相等待到达屏障点后继续。
  • 适用场景:线程按阶段同步执行。
  • 示例
    import java.util.concurrent.*;
    
    public class CyclicBarrierExample {
        public static void main(String[] args) {
            CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("Barrier passed"));
    
            Runnable task = () -> {
                try {
                    System.out.println(Thread.currentThread().getName() + " ready");
                    barrier.await();
                    System.out.println(Thread.currentThread().getName() + " running");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            };
    
            new Thread(task, "T1").start();
            new Thread(task, "T2").start();
            new Thread(task, "T3").start();
        }
    }
    
  • 输出(顺序可能不同):
    T1 ready
    T2 ready
    T3 ready
    Barrier passed
    T1 running
    T2 running
    T3 running
    
  • 优点:可重用,支持阶段性同步。
  • 缺点:线程数需固定。
4. 使用 synchronizedwait()/notify()
  • 原理:通过锁和条件变量手动控制顺序。
  • 适用场景:复杂顺序需求。
  • 示例
    public class WaitNotifyExample {
        private static final Object lock = new Object();
        private static volatile int step = 1;
    
        public static void main(String[] args) {
            Thread t1 = new Thread(() -> {
                synchronized (lock) {
                    System.out.println("Thread 1");
                    step = 2;
                    lock.notifyAll();
                }
            });
            Thread t2 = new Thread(() -> {
                synchronized (lock) {
                    while (step != 2) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("Thread 2");
                    step = 3;
                    lock.notifyAll();
                }
            });
            Thread t3 = new Thread(() -> {
                synchronized (lock) {
                    while (step != 3) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("Thread 3");
                }
            });
    
            t3.start();
            t2.start();
            t1.start();
        }
    }
    
  • 输出
    Thread 1
    Thread 2
    Thread 3
    
  • 优点:灵活性高。
  • 缺点:代码复杂,易出错。
5. 使用 Semaphore
  • 原理:通过许可控制线程执行顺序。
  • 适用场景:顺序执行资源访问。
  • 示例
    import java.util.concurrent.*;
    
    public class SemaphoreExample {
        public static void main(String[] args) {
            Semaphore s1 = new Semaphore(1);
            Semaphore s2 = new Semaphore(0);
            Semaphore s3 = new Semaphore(0);
    
            new Thread(() -> {
                try {
                    s1.acquire();
                    System.out.println("Thread 1");
                    s2.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
    
            new Thread(() -> {
                try {
                    s2.acquire();
                    System.out.println("Thread 2");
                    s3.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
    
            new Thread(() -> {
                try {
                    s3.acquire();
                    System.out.println("Thread 3");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
    
  • 输出
    Thread 1
    Thread 2
    Thread 3
    
  • 优点:直观控制顺序。
  • 缺点:需要多个信号量。

问题分析与知识点联系

“控制线程执行顺序”是并发编程中的常见需求,与问题列表中的多个知识点相关:

  1. Java 中的线程同步
    synchronizedSemaphore 等实现顺序控制。

  2. Java 中的线程通信
    wait()/notify()CountDownLatchCyclicBarrier 用于线程间协调。

  3. Java 使用过哪些并发工具类
    CountDownLatchCyclicBarrierSemaphore 是常用工具。

  4. 线程的生命周期
    join()await() 影响线程状态(如 WAITING)。

  5. Java 中的死锁
    不当使用同步工具可能导致死锁,需谨慎设计。

总结来说,Java 提供了多种方法控制线程执行顺序,从简单的 join() 到复杂的 Semaphore 组合,适用于不同场景。选择方法需根据线程数量、顺序复杂度和重用性要求,是并发编程中协调线程行为的核心技能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

+720

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

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

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

打赏作者

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

抵扣说明:

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

余额充值