问答题796/1053有三个线程T1,T2,T3,怎么确保它们按顺序执行?

难度:
2021-11-02 创建

参考答案:

确保多个线程按顺序执行是一个常见的多线程编程问题。你希望线程 T1T2T3 按顺序依次执行,即 T1 先执行,执行完毕后 T2 执行,再然后是 T3 执行。

有几种常见的方法来实现线程按顺序执行。下面是几种常用的方式:

1. 使用 join() 方法

Thread.join() 方法使得当前线程等待调用 join() 的线程执行完毕。你可以通过让每个线程在前一个线程完成后执行来实现线程顺序执行。

1public class ThreadSequenceExample { 2 public static void main(String[] args) throws InterruptedException { 3 Thread T1 = new Thread(() -> { 4 System.out.println("T1 is running"); 5 }); 6 7 Thread T2 = new Thread(() -> { 8 System.out.println("T2 is running"); 9 }); 10 11 Thread T3 = new Thread(() -> { 12 System.out.println("T3 is running"); 13 }); 14 15 T1.start(); 16 T1.join(); // 主线程等待 T1 执行完毕 17 18 T2.start(); 19 T2.join(); // 主线程等待 T2 执行完毕 20 21 T3.start(); 22 T3.join(); // 主线程等待 T3 执行完毕 23 } 24}

解释:

  • T1.start() 启动 T1 线程。
  • T1.join() 主线程等待 T1 执行完毕再继续。
  • 依此类推,T2T1 执行完毕后启动,T3T2 执行完毕后启动。
  • 这样,T1T2T3 按顺序执行。

2. 使用 CountDownLatch

CountDownLatch 是一个同步工具类,它允许一个或多个线程等待直到某些操作完成。你可以用它来控制线程按顺序执行。

1import java.util.concurrent.CountDownLatch; 2 3public class ThreadSequenceExample { 4 public static void main(String[] args) throws InterruptedException { 5 CountDownLatch latch1 = new CountDownLatch(1); // 用于控制 T2 等待 T1 6 CountDownLatch latch2 = new CountDownLatch(1); // 用于控制 T3 等待 T2 7 8 Thread T1 = new Thread(() -> { 9 System.out.println("T1 is running"); 10 latch1.countDown(); // T1 执行完毕后释放 latch1 11 }); 12 13 Thread T2 = new Thread(() -> { 14 try { 15 latch1.await(); // 等待 T1 执行完毕 16 System.out.println("T2 is running"); 17 latch2.countDown(); // T2 执行完毕后释放 latch2 18 } catch (InterruptedException e) { 19 e.printStackTrace(); 20 } 21 }); 22 23 Thread T3 = new Thread(() -> { 24 try { 25 latch2.await(); // 等待 T2 执行完毕 26 System.out.println("T3 is running"); 27 } catch (InterruptedException e) { 28 e.printStackTrace(); 29 } 30 }); 31 32 T1.start(); 33 T2.start(); 34 T3.start(); 35 } 36}

解释:

  • latch1 用来控制 T2 等待 T1 完成,latch2 用来控制 T3 等待 T2 完成。
  • 每个线程完成工作后,调用 countDown() 方法释放对应的 latch,让下一个线程可以开始执行。
  • T1 执行完毕后,latch1.countDown() 被调用,释放 T2T2 执行完后,latch2.countDown() 被调用,释放 T3,实现线程按顺序执行。

3. 使用 Semaphore 控制线程顺序

Semaphore 是一个信号量类,它通常用于控制多个线程访问共享资源的数量。在这个例子中,我们用 Semaphore 来控制线程的执行顺序。

1import java.util.concurrent.Semaphore; 2 3public class ThreadSequenceExample { 4 public static void main(String[] args) throws InterruptedException { 5 Semaphore semaphoreT1 = new Semaphore(1); // 让 T1 先执行 6 Semaphore semaphoreT2 = new Semaphore(0); // 让 T2 等待 T1 执行 7 Semaphore semaphoreT3 = new Semaphore(0); // 让 T3 等待 T2 执行 8 9 Thread T1 = new Thread(() -> { 10 try { 11 System.out.println("T1 is running"); 12 semaphoreT2.release(); // T1 执行完后释放 T2 13 } catch (Exception e) { 14 e.printStackTrace(); 15 } 16 }); 17 18 Thread T2 = new Thread(() -> { 19 try { 20 semaphoreT2.acquire(); // 等待 T1 执行完毕 21 System.out.println("T2 is running"); 22 semaphoreT3.release(); // T2 执行完后释放 T3 23 } catch (InterruptedException e) { 24 e.printStackTrace(); 25 } 26 }); 27 28 Thread T3 = new Thread(() -> { 29 try { 30 semaphoreT3.acquire(); // 等待 T2 执行完毕 31 System.out.println("T3 is running"); 32 } catch (InterruptedException e) { 33 e.printStackTrace(); 34 } 35 }); 36 37 T1.start(); 38 T2.start(); 39 T3.start(); 40 } 41}

解释:

  • Semaphore semaphoreT1 初始化为 1,允许 T1 执行。
  • semaphoreT2semaphoreT3 初始化为 0,保证 T2T3 在前一个线程完成后才能执行。
  • 每个线程完成后,通过调用 release() 方法释放下一个线程。
  • T2T1 执行完后可以开始,T3T2 执行完后可以开始。

4. 使用 LockCondition(高级控制)

Condition 是 Java 并发包中的一种工具,结合 Lock 使用,可以精确控制线程的执行顺序。

1import java.util.concurrent.locks.Condition; 2import java.util.concurrent.locks.Lock; 3import java.util.concurrent.locks.ReentrantLock; 4 5public class ThreadSequenceExample { 6 public static void main(String[] args) throws InterruptedException { 7 Lock lock = new ReentrantLock(); 8 Condition conditionT1 = lock.newCondition(); 9 Condition conditionT2 = lock.newCondition(); 10 Condition conditionT3 = lock.newCondition(); 11 12 Thread T1 = new Thread(() -> { 13 lock.lock(); 14 try { 15 System.out.println("T1 is running"); 16 conditionT2.signal(); // 通知 T2 可以执行 17 } finally { 18 lock.unlock(); 19 } 20 }); 21 22 Thread T2 = new Thread(() -> { 23 lock.lock(); 24 try { 25 conditionT2.await(); // 等待 T1 执行完 26 System.out.println("T2 is running"); 27 conditionT3.signal(); // 通知 T3 可以执行 28 } catch (InterruptedException e) { 29 e.printStackTrace(); 30 } finally { 31 lock.unlock(); 32 } 33 }); 34 35 Thread T3 = new Thread(() -> { 36 lock.lock(); 37 try { 38 conditionT3.await(); // 等待 T2 执行完 39 System.out.println("T3 is running"); 40 } catch (InterruptedException e) { 41 e.printStackTrace(); 42 } finally { 43 lock.unlock(); 44 } 45 }); 46 47 T1.start(); 48 T2.start(); 49 T3.start(); 50 } 51}

解释:

  • lock 确保对共享资源的独占访问。
  • Condition 用来协调线程之间的等待与通知。
  • 线程 T2T1 完成后等待,线程 T3T2 完成后等待,保证按顺序执行。

最近更新时间:2024-12-12