当前位置: 首页 > news >正文

多线程轮流打印 ABC

写作初衷:网上多线程轮流打印 ABC 的例子已经很多了,但不是自己的逻辑沉淀不出知识。
最近考虑通过实现 多线程轮流打印 ABC, 多线程累加求和,简单总结下并发相关的知识点

内容说明:

  1. 仅实现了 volatile + synchronized + wait-notify 机制,目的是尽可能从简单的逻辑过渡
  2. 初步尝试了代码优化,即减少代码冗余,进行代码重构

1. 重构前:多个 Runnable 实现类

package com.youga.concurrent;

class ThreadPrintA implements Runnable{

    String s;
    ThreadPrintA(String s){
        this.s = s;
    }
    @Override
    public void run() {
        Object o = new Object();
        synchronized (o){
            if(!s.equals("A")){
                try {
                    o.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.print(s + " ");
            o.notify();
        }
    }
}
class ThreadPrintB implements Runnable{

    String s;
    ThreadPrintB(String s){
        this.s = s;
    }
    @Override
    public void run() {
        Object o = new Object();
        synchronized (o){
            if(!s.equals("B")){
                try {
                    o.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.print(s + " ");
            o.notify();
        }
    }
}
class ThreadPrintC implements Runnable{

    String s;
    ThreadPrintC(String s){
        this.s = s;
    }
    @Override
    public void run() {
        Object o = new Object();
        synchronized (o){
            if(!s.equals("C")){
                try {
                    o.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println(s);
            o.notify();
        }
    }
}

/**
 * 需求分析:现在仅实现了竞争打印,需要保证次序打印
 * ① 按 A,B,C 次序打印
 * ② 循环打印
 */
public class PrintAbc {
    public static void main(String[] args) throws InterruptedException {
        while(true){
            new Thread(new ThreadPrintA("A")).start();
            Thread.sleep(10);
            new Thread(new ThreadPrintB("B")).start();
            Thread.sleep(10);
            new Thread(new ThreadPrintC("C")).start();
            Thread.sleep(10);
        }
    }
}

tips :若 main() 函数中启动每个线程时未加延迟,则不能保证 A B C 线程是按照启动顺序执行的

基本逻辑:在每个 Runnable 实现类中判断传入参数是否为待打印字符,不是则阻塞至对应的线程打印完毕

重构逻辑:利用 ABC 三者的关系,修改字符串判断的逻辑:通过类变量动态获取当前需要打印的字符串

2. 重构后:一个 Runnable 实现类

class ThreadPrint implements Runnable{
    private static volatile int cnt = 0;
    private String s;
    ThreadPrint(String s){
        this.s = s;
    }
    @Override
    public void run() {
        Object o = new Object();
        synchronized (o){
            String ss = String.valueOf((char)('A' + cnt));
            if(!s.equals(ss)){
                try {
                    o.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.print(s);
            o.notify();
            if(cnt == 2) System.out.println();
            cnt = (cnt + 1) % 3;
        }
    }
}

/**
 * ① 按 A,B,C 次序打印
 * ② 循环打印
 * ③ 代码重构
 */
public class PrintAbc1 {
    public static void main(String[] args) throws InterruptedException {
        while(true){
            for(int i = 0; i < 3; i++){
                new Thread(new ThreadPrint(String.valueOf((char)('A' + i)))).start();
                Thread.sleep(100);
            }
        }
    }
}

为啥用 volatile 和 static 修饰 cnt,这就不说了,说出来的都是别人总结出来的,自己实践下最好

实践之后也不是自己的,因为还涉及到 语言特性,编译原理,CPU,指令架构…

摸清楚这些后,还不是你的,做人要诚实,但也要有所追求,认识这点的意义在于:或许有一天有些东西是属于你的

我老是觉得:从这个层面来想,学习 Java 是可以 上穷碧落下黄泉的,这是我迄今为止依然坚持的原因,即使这是 2022 年的寒秋

反思了下:

  1. 博客还是要尽可能简洁
  2. 已有的结论尽可能少写,实验得出的结论可分析一下
  3. 加强实践,代码为先

相关文章:

  • SpringCloud整合spring security+ oauth2+Redis实现认证授权
  • 轻量级开源ROS 的机器人设备(一)
  • java基于微信小程序的校园报修系统 uniapp小程序
  • IDEA详细配置『JDK | Maven | Tomcat』
  • 视觉目标检测大模型套件detrex-调研
  • Docker搭建私有镜像仓库与WordPress
  • 嵌入式软件工程师面试题(七)
  • 力扣(412.516)补8.21
  • 数据集 | 基于计算机视觉的医学影像处理数据集
  • Apache RocketMQ 在阿里云大规模商业化实践之路
  • 《uni-app》一个非canvas的飞机对战小游戏实现-敌机模型实现
  • HTML生日快乐代码 html生日快乐网站制作 html烟花表白网站制作
  • 环境卫生学重点笔记
  • 改进搜索机制的单纯形法引导麻雀搜索算法-附代码
  • 带你吃透Servlet核心编程下篇(完整图文教程)
  • 【译】理解JavaScript:new 关键字
  • 03Go 类型总结
  • conda常用的命令
  • Javascript基础之Array数组API
  • SAP云平台里Global Account和Sub Account的关系
  • UEditor初始化失败(实例已存在,但视图未渲染出来,单页化)
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • vue-router 实现分析
  • Web设计流程优化:网页效果图设计新思路
  • WordPress 获取当前文章下的所有附件/获取指定ID文章的附件(图片、文件、视频)...
  • 理解在java “”i=i++;”所发生的事情
  • 模型微调
  • 如何将自己的网站分享到QQ空间,微信,微博等等
  • 三分钟教你同步 Visual Studio Code 设置
  • 推荐一款sublime text 3 支持JSX和es201x 代码格式化的插件
  • 一天一个设计模式之JS实现——适配器模式
  • 用quicker-worker.js轻松跑一个大数据遍历
  • 深度学习之轻量级神经网络在TWS蓝牙音频处理器上的部署
  • SAP CRM里Lead通过工作流自动创建Opportunity的原理讲解 ...
  • ​【已解决】npm install​卡主不动的情况
  • # Maven错误Error executing Maven
  • #我与Java虚拟机的故事#连载16:打开Java世界大门的钥匙
  • #中国IT界的第一本漂流日记 传递IT正能量# 【分享得“IT漂友”勋章】
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
  • (9)YOLO-Pose:使用对象关键点相似性损失增强多人姿态估计的增强版YOLO
  • (poj1.2.1)1970(筛选法模拟)
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (附源码)计算机毕业设计SSM智慧停车系统
  • (四)Linux Shell编程——输入输出重定向
  • (算法二)滑动窗口
  • (心得)获取一个数二进制序列中所有的偶数位和奇数位, 分别输出二进制序列。
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (原创)boost.property_tree解析xml的帮助类以及中文解析问题的解决
  • (转)h264中avc和flv数据的解析
  • (转载)VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)
  • *1 计算机基础和操作系统基础及几大协议
  • .aanva
  • .bashrc在哪里,alias妙用
  • .gitignore文件—git忽略文件