Java实现三个线程顺序打印

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

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


方案一:使用 ReentrantLockCondition(推荐)

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

java 复制代码
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();
    }
}

方案二:使用 synchronizedwait/notifyAll(最基础)

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

java 复制代码
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();
    }
}

相关推荐
心之伊始14 小时前
Spring AI Structured Output 实战:把大模型返回稳定转成 Java DTO
java·spring boot·大模型·spring ai·structured output
星辰_mya14 小时前
限流、漏斗桶和令牌桶的区别
java·开发语言·面试·架构·高并发
Shadow(⊙o⊙)14 小时前
信号1.0,信号概念、signal()处理、前后台进程、闹钟设置、初识信号三张表。
linux·运维·服务器·开发语言·c++
(Charon)14 小时前
【C++ 面试高频:STL 容器 vector、map、unordered_map 总结】
开发语言·c++·面试
我是一颗柠檬14 小时前
【Java项目技术亮点】滑动窗口限流算法
java·开发语言·算法
我登哥MVP14 小时前
SpringCloud Alibaba 核心组件解析:分布式事务(Seata)
java·spring boot·分布式·spring·spring cloud·java-ee·intellij-idea
于指尖飞舞14 小时前
java后端面试题(jvm极简)
java·开发语言·jvm
Seven9714 小时前
面试官:你们项目里的线程池是怎么用的?怎么管理的?
java
java_cj14 小时前
从kubectl源码学Cobra:打造专业级Go命令行工具的完整实践
运维·开发语言·后端·云原生·golang·kubernetes·k8s
xieliyu.14 小时前
Java数据结构:从0开始手搓Hash桶
java·数据结构·哈希算法