LeetCode 1114. 按序打印

目录

[LeetCode 1114. 按序打印:多线程顺序控制的核心逻辑(附完整代码)](#LeetCode 1114. 按序打印:多线程顺序控制的核心逻辑(附完整代码))

一、题目核心需求

[二、解题核心思路:锁 + 标志位 + 线程通信](#二、解题核心思路:锁 + 标志位 + 线程通信)

三、完整代码实现

四、关键知识点总结


LeetCode 1114. 按序打印:多线程顺序控制的核心逻辑(附完整代码)

最近练习了 LeetCode 的「按序打印」问题,正好借此梳理多线程顺序控制的核心思路 ------ 这是并发编程的基础考点,分享给刚学 JUC 的朋友~

一、题目核心需求

实现一个Foo类,让三个线程分别调用first()、second()、third(),严格按first→second→third的顺序打印(即使线程启动顺序打乱)。

二、解题核心思路:锁 + 标志位 + 线程通信

要让多线程按固定顺序执行,核心是 **"控制前置方法的执行状态"**,这里用「synchronized锁 + 布尔标志位 + wait/notifyAll通信」实现:

  1. 标志位 :用firsttest、secondtest标记 "前序方法是否执行完成";
  2. 专属锁对象 :创建private final Object lock作为同步锁(避免外部干扰);
  3. 线程通信 :用lock.wait()让线程等待(释放锁),lock.notifyAll()唤醒后续线程。

三、完整代码实现

复制代码
class Foo {
    // 标志位:标记前序方法是否执行完成
    private boolean firsttest = false;
    private boolean secondtest = false;
    // 专属锁对象:保证锁的封闭性和唯一性
    private final Object lock = new Object();

    public Foo() {
    }

    public void first(Runnable printFirst) throws InterruptedException {
        synchronized (lock) {
            // 执行first逻辑
            printFirst.run();
            // 标记first已完成
            firsttest = true;
            // 唤醒等待lock的线程(second/third)
            lock.notifyAll();
        }
    }

    public void second(Runnable printSecond) throws InterruptedException {
        synchronized (lock) {
            // 循环等待:直到first执行完成(防止虚假唤醒)
            while (!firsttest) {
                lock.wait();
            }
            // 执行second逻辑
            printSecond.run();
            // 标记second已完成
            secondtest = true;
            // 唤醒等待lock的线程(third)
            lock.notifyAll();
        }
    }

    public void third(Runnable printThird) throws InterruptedException {
        synchronized (lock) {
            // 循环等待:直到second执行完成
            while (!secondtest) {
                lock.wait();
            }
            // 执行third逻辑
            printThird.run();
        }
    }
}

四、关键知识点总结

  1. 专属锁对象的设计 用private final Object lock而不是this:

    • private:避免外部代码滥用锁;
    • final:防止锁对象被意外替换;
    • Object:轻量化,仅用其 "对象身份" 做锁。
  2. 为什么用while而不是if判断标志位? 防止虚假唤醒 (线程可能无原因被唤醒),while会二次检查标志位,确保只有前序方法执行完才继续。

  3. wait/notifyAll的作用

    • lock.wait():释放锁,让前序线程执行;
    • lock.notifyAll():唤醒所有等待该锁的线程,传递 "前序已完成" 的信号。
相关推荐
蜗牛一步步往上爬2 小时前
第十六章 C++语言在深度学习中的应用
开发语言·c++·深度学习
这个昵称不容易3 小时前
SpringBoot「衣依」服装销售平台:144个Java文件180个接口,从挑衣服到收货评价整条链路都在
java·springboot·毕设
计算机毕设定制辅导-无忧学长3 小时前
《基于微信小程序的居家医疗陪护预约系统设计与实现》
java·spring boot·微信小程序·uniapp·居家医疗陪护预约系统
张张123y4 小时前
DSH 插件调试避坑:client.js 设置面板、热重载与高频报错排查表
开发语言·javascript·人工智能·开源·ecmascript·后端开发·ai agent
文丑颜不良啊5 小时前
LeetCode2221~2240题目解析
java·leetcode
秋饼5 小时前
Computer Use Agent Java 落地实战:感知-行动循环、执行器与安全围栏生产级实现
java·ai·技术分享·后端开发
Navigator_Z5 小时前
LeetCode //C - 1317. Convert Integer to the Sum of Two No-Zero Integers
c语言·算法·leetcode
D e re k ZH6 小时前
C++ 标准库算法全景指南
数据结构·c++·算法
冻柠檬飞冰走茶6 小时前
字母移动游戏题解:贪心求最长可保留连续子串(附 C 实现)
c语言·开发语言·数据结构·算法·动态规划