Java实现三个线程进行顺序打印的两种方案

 更新时间:2026年01月04日 09:47:17   作者:Chen不旧  
三个线程按顺序打印是一个经典的并发编程面试题,通常要求线程 A 打印 1,线程 B 打印 2,线程 C 打印 3,然后循环往复,所以本文给大家介绍了Java实现三个线程进行顺序打印的两种方案的相关资料,需要的朋友可以参考下

引言

“三个线程按顺序打印”是一个经典的并发编程面试题,通常要求线程 A 打印 1,线程 B 打印 2,线程 C 打印 3,然后循环往复。

实现这个逻辑的核心在于线程间的通信(Signaling)。我们可以使用 Java 的 synchronized 配合 wait/notify,或者更现代的 ReentrantLock 配合 Condition

方案一:使用ReentrantLock和Condition(推荐)

这是最清晰的方案。我们为每个线程创建一个“信号灯”(Condition),手动控制唤醒哪一个。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SequencePrint {
    private final Lock lock = new ReentrantLock();
    private final Condition cond1 = lock.newCondition();
    private final Condition cond2 = lock.newCondition();
    private final Condition cond3 = lock.newCondition();
    private int state = 1; // 当前应该打印的序号

    public void print(String name, int targetState, Condition current, Condition next) {
        for (int i = 0; i < 10; i++) { // 假设打印10轮
            lock.lock();
            try {
                // 如果还没轮到我,就一直等着
                while (state != targetState) {
                    current.await();
                }
                System.out.print(name + " ");
                // 修改状态并唤醒下一个线程
                state = (targetState % 3) + 1;
                next.signal();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) {
        SequencePrint sp = new SequencePrint();
        new Thread(() -> sp.print("A", 1, sp.cond1, sp.cond2)).start();
        new Thread(() -> sp.print("B", 2, sp.cond2, sp.cond3)).start();
        new Thread(() -> sp.print("C", 3, sp.cond3, sp.cond1)).start();
    }
}

方案二:使用synchronized和wait/notifyAll(最基础)

这种方式代码最少,但效率略低,因为 notifyAll() 会唤醒所有等待线程,不满足条件的线程会被唤醒后再次检查并挂起。

public class WaitNotifyPrint {
    private int state = 1;
    private final Object lock = new Object();

    public void print(String name, int targetState) {
        for (int i = 0; i < 10; i++) {
            synchronized (lock) {
                while (state != targetState) {
                    try { lock.wait(); } catch (InterruptedException e) {}
                }
                System.out.print(name);
                state = (state % 3) + 1;
                lock.notifyAll(); // 唤醒所有人,让他们竞争判断 state
            }
        }
    }

    public static void main(String[] args) {
        WaitNotifyPrint wnp = new WaitNotifyPrint();
        new Thread(() -> wnp.print("A", 1)).start();
        new Thread(() -> wnp.print("B", 2)).start();
        new Thread(() -> wnp.print("C", 3)).start();
    }
}

到此这篇关于Java实现三个线程进行顺序打印的两种方案的文章就介绍到这了,更多相关Java三个线程顺序打印内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java中多个@Scheduled定时器不执行的解决方法

    java中多个@Scheduled定时器不执行的解决方法

    在应用开发中经常需要一些周期性的操作,比如每5分钟执行某一操作等,这篇文章主要给大家介绍了关于java中多个@Scheduled定时器不执行的解决方法,需要的朋友可以参考下
    2023-04-04
  • SpringBoot配置Https访问的详细步骤

    SpringBoot配置Https访问的详细步骤

    HTTP(Hypertext transfer protocal)是一种详细规定了浏览器和万维网服务器之间相互通信的规则,通过因特网传送万维网文档的数据传送协议,这篇文章主要介绍了SpringBoot配置Https访问的详细步骤,需要的朋友可以参考下
    2024-02-02
  • mybatisPlus更新字段值为null的解决方案

    mybatisPlus更新字段值为null的解决方案

    在使用mybatis-plus时,发现当前端传入的值为null值时,结果无论怎么操作后端都不执行更新null字段的操作,下面这篇文章主要给大家介绍了关于mybatisPlus更新字段值为null的解决方案,需要的朋友可以参考下
    2023-04-04
  • 分享一个你不知道的Java异常实现的缺陷

    分享一个你不知道的Java异常实现的缺陷

    Java中一个大家熟知的知识点就是异常捕获,try...catch...finally组合,但是很多人不知道这里面有一个关于Java的缺陷,或者说是异常实现的一点不足之处。本文就通过一个很简单的实验给大家演示下效果玩玩儿,希望大家能觉得有趣
    2022-12-12
  • Java使用带标签的break语句跳出多层循环

    Java使用带标签的break语句跳出多层循环

    本文介绍了Java中的带标签的break语句,它允许跳出指定的外层循环,适用于多层嵌套循环场景,通过示例解释了如何在方法中优雅地跳出多层循环而不会影响方法其余逻辑,实际应用场景如检测图像是否为黑屏,总结了标签的使用注意事项和替代方案,需要的朋友可以参考下
    2026-05-05
  • Springboot-Management的项目实践

    Springboot-Management的项目实践

    本文主要介绍了Springboot-Management的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05
  • java加密枝术深入理解

    java加密枝术深入理解

    java.security包中的MessageDigest类提供了计算消息摘要的方法,本文将详细介绍,需要了解的朋友可以参考下
    2012-11-11
  • Java守护线程实例详解_动力节点Java学院整理

    Java守护线程实例详解_动力节点Java学院整理

    在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程) 。下面通过本文给大家分享java守护线程实例详解,需要的朋友参考下吧
    2017-06-06
  • 使用Java调用Yolo模型的基本步骤

    使用Java调用Yolo模型的基本步骤

    Yolo(You Only Look Once)是一种基于深度学习的目标检测算法,它可以在一张图像中同时检测出多个目标,并给出它们的位置和类别,这篇文章主要介绍了使用Java调用Yolo模型的基本步骤,需要的朋友可以参考下
    2024-03-03
  • Spring中的底层架构核心概念类型转换器详解

    Spring中的底层架构核心概念类型转换器详解

    这篇文章主要介绍了Spring中的底层架构核心概念类型转换器详解,本文结合示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-12-12

最新评论