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();
    }
}

相关推荐
2601_949146533 分钟前
C语言语音通知接口接入教程:如何使用C语言直接调用语音预警API
c语言·开发语言
曹牧8 分钟前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
KYGALYX14 分钟前
服务异步通信
开发语言·后端·微服务·ruby
zmzb010321 分钟前
C++课后习题训练记录Day98
开发语言·c++
爬山算法1 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
kfyty7251 小时前
集成 spring-ai 2.x 实践中遇到的一些问题及解决方案
java·人工智能·spring-ai
猫头虎1 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven
李少兄1 小时前
在 IntelliJ IDEA 中修改 Git 远程仓库地址
java·git·intellij-idea
YUJIANYUE1 小时前
PHP纹路验证码
开发语言·php
忆~遂愿1 小时前
ops-cv 算子库深度解析:面向视觉任务的硬件优化与数据布局(NCHW/NHWC)策略
java·大数据·linux·人工智能