多线程轮流打印

news2024/11/29 13:36:35

一、背景

面试的时候,有一个高频的笔试题:

让2个线程轮流打印,a线程是打印ABCDEFGHIJ,b线程是打印1、2、3、4、5、6、7、8、9、10

二、原理

这种类型的面试题,主要是考察object的wait()方法和notify()方法的使用

wait()方法用法:

o.wait()会让正在o对象上活动的当前线程进入等待状态,并且释放之前占用的o对象的锁

notify()方法用法:

o.notify()唤醒正在o对象上等待的线程, 只会通知,不会释放之前占用的o对象的锁

三、用法

2个线程轮流打印,a线程是打印ABCDEFGHIJ,b线程是打印1、2、3、4、5、6、7、8、9、10

package com.iflytek.sda;

import java.util.Arrays;
import java.util.List;

public class ThreadTest {

    private static final Object lock = new Object();

    private static boolean ifPrint = false;

    public static void main(String[] args) {
        Thread ta = new Thread(() ->{
            // 要打印的list
            List<String> list = Arrays.asList("A","B","C","D","E","F","G","H","I","J");
                for (int i = 0; i < list.size(); i++){
                    synchronized (lock) {
                        // 如果ifPrint的值为true,就会进入等待状态
                        while (ifPrint) {
                            try{
                                lock.wait();
                            }catch (Exception e){

                            }
                        }
                        // 到了这一步,说明ifPrint的值为false,然后就会打印
                        System.out.print(list.get(i));
                        // 修改ifPrint的值为true,这样再次进入该方法时会进入等待状态,不会进行打印
                        ifPrint = true;
                        // 唤醒正在lock对象上等待的线程
                        lock.notify();
                    }
                }
        });
        Thread tb = new Thread(() ->{
            for (int i = 0; i < 10; i++){
                synchronized (lock) {
                    // 如果ifPrint的值为false,就会进入等待状态
                    while (!ifPrint) {
                        try{
                            lock.wait();
                        }catch (Exception e){

                        }
                    }
                    // 到了这一步,说明ifPrint的值为true,然后就会打印
                    System.out.print(i+1);
                    // 修改ifPrint的值为false,这样再次进入该方法时会进入等待状态,不会进行打印
                    ifPrint = false;
                    // 唤醒正在lock对象上等待的线程
                    lock.notify();
                }
            }
        });
        ta.start();
        tb.start();
    }
}

一开始,ifPrint为false,此时,ta线程会进行打印,打印A;tb线程会处于等待状态;

等ta打印完毕,修改ifPrint为true,并且唤醒其它等待线程。

此时,ta线程会处于等待状态;tb线程会进行打印,打印1

等tb打印完毕,修改ifPrint为false,并且唤醒其它等待线程。

此时,ta线程会进行打印,打印B;tb线程会处于等待状态;

....

以此类推:

 四、升级

上面是2个线程,可以通过true、false的两种状态来区分,那如果是3个线程呢,4个线程呢,要怎么办?

3个线程,轮流打印,第一个线程只打印A,第二个线程只打印B,第三个线程只打印C

package com.iflytek.sda;


public class ThreadTest2 {

    private static Integer flag = 1;

    private static final Object lock = new Object();

    public static void main(String[] args) {

        Thread threadA = new Thread(()->{
            for (int i = 0 ; i < 10; i++){
                synchronized (lock){
                    while(flag != 1){
                        try{
                            lock.wait();
                        }catch (Exception e){

                        }
                    }
                    System.out.print("A");
                    flag = 2;
                    lock.notifyAll();
                }
            }
        });
        Thread threadB = new Thread(()->{
            for (int i = 0 ; i < 10; i++){
                synchronized (lock){
                    while(flag != 2){
                        try{
                            lock.wait();
                        }catch (Exception e){

                        }
                    }
                    System.out.print("B");
                    flag = 3;
                    lock.notifyAll();
                }
            }
        });
        Thread threadC = new Thread(()->{
            for (int i = 0 ; i < 10; i++){
                synchronized (lock){
                    while(flag != 3){
                        try{
                            lock.wait();
                        }catch (Exception e){

                        }
                    }
                    System.out.print("C");
                    flag = 1;
                    lock.notifyAll();
                }
            }
        });
        threadA.start();
        threadB.start();
        threadC.start();
    }
}

这里的代码写在同一个类里面,标志位写在最上面可以共用,实际用法中都不在一个类里面,要怎么办呢?

package com.example.demo.thread;

public class ThreadPrint {

    public static Integer flag = 1;
    public static void main(String[] args) {

        Thread ta = new Thread(new ThreadA());
        Thread tb = new Thread(new ThreadB());
        ta.start();
        tb.start();
    }
}

class ThreadA implements Runnable{

    @Override
    public void run() {
        for(int i = 0 ; i < 10; i++){
            synchronized (ThreadPrint.class){
                while (ThreadPrint.flag != 1){
                    try {
                        ThreadPrint.class.wait();
                    }catch (Exception e){

                    }
                }
                System.out.print("1");
                ThreadPrint.flag = 2;
                ThreadPrint.class.notifyAll();
            }
        }
    }
}

class ThreadB implements Runnable{

    @Override
    public void run() {
        for(int i = 0 ; i < 10; i++){
            synchronized (ThreadPrint.class){
                while (ThreadPrint.flag != 2){
                    try {
                        ThreadPrint.class.wait();
                    }catch (Exception e){

                    }
                }
                System.out.print("A");
                ThreadPrint.flag = 1;
                ThreadPrint.class.notifyAll();
            }
        }
    }
}

好几个线程同理,

另外,超过两个线程就需要使用notifyAll,唤醒对象上的所有线程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/49140.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

spring整合Mybatis-P23,24,25

复习Mybatis&#xff08;都是之前的内容&#xff0c;不再解释&#xff09; 6个需要修改或创建的文件 UserMapper package com.Li.mapper;import com.Li.pojo.User;import java.util.List;public interface UserMapper {public List<User> selectUser(); }UserMapper.xm…

如何全面提升架构设计的质量

低成本 低成本本质上是对架构的一种约束&#xff0c;与高性能等架构是冲突的 手段和应用 先设计架构方案&#xff0c;再看如何降低成本 优化 引入缓存虚拟化、容器化性能调优采用高性能硬件采用开源方案 创新 NoSQL vs SQLSQL vs 倒排索引Hadoop vs MySQL 安全性 复杂…

《码出高效:Java开发手册》 四-走进JVM

前言 JVM是java中底层的知识&#xff0c;这里的内容比较复杂&#xff0c;对于一些软件编程&#xff0c;会经常使用&#xff0c;但很多业务其实碰不到这里的知识&#xff0c;下图为目录 介绍 JVM&#xff0c;java虚拟机&#xff0c;它的前身是99年的hotspot java虚拟机&…

vue 计算属性未重新计算 / computed 未触发 / computed 原理源码分析

点击可打开demo 这里在一秒后改了数组里value属性的值 虽然数据有更新&#xff0c;但打开控制台&#xff0c;可以发现computed函数只在初始化时执行了一次 按理说一秒后改变了value值&#xff0c;应该执行两次才对呀&#xff1f; 但如果computed属性这样写&#xff0c;明确写…

数据分析之大数据分析

一 什么是大数据分析 大数据是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合&#xff0c;是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。大数据的特点可以概括为5个V&#xff1a;数据量大&…

当湿度达到70蜂鸣器警报

1.编写设备树&#xff0c;添加蜂鸣器等设备 驱动代码&#xff1a; #include <linux/init.h> #include <linux/module.h> #include <linux/i2c.h> #include <linux/fs.h> #include <linux/uaccess.h> #include <linux/device.h> #include …

QCSPCChart for Java R3x0 Crack

Java 的 SPC 控制图工具 版本 3.04 QCSPCChart添加变量控制图&#xff08;X-Bar R、X-Bar Sigma、Individual Range、Median Range、EWMA、MA、MAMR、MAMS 和 CuSum 图&#xff09;、属性控制图&#xff08;p-、np-、c-、u- 和DPMO 图&#xff09;、频率直方图和 Pareto 图到…

[附源码]Python计算机毕业设计Django的旅游景点管理系统的设计与实现

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

[附源码]Python计算机毕业设计SSM老年公寓管理系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

计算机编程

文章目录计算机编程计算机编程语言计算机编程 人与人之间信息&#xff08;如想法、思想等&#xff09;的交流和传递&#xff0c;需要借助双方都能听得懂的语言。人和计算机之间实现交流也是如此&#xff0c;需要借助一种人和计算机都能理解的语言&#xff0c;这种语言称为编程…

LCHub低代码社区:旧的低代码,腾讯怎么讲出新故事

腾讯微搭的对手从来都不是钉钉。 低代码是 " 旧瓶装新酒 " 吗? 低代码风潮在国内兴盛已有两年,但也并不是已经被所有人接受,有不少开发者还保有否定、抵触的态度。 那为什么我们还认为这是一个不可逆的趋势呢? 这里先看下被否定的原因,LCHub在调研中听到的主…

怎么把PDF转换成图片?这三种转换方法都可以实现

怎么把PDF文件的内容转换成图片来使用呢&#xff1f;大家在办公或者是学习的过程中没少使用过PDF文件&#xff0c;有的文件我们翻阅起来会比较费时间&#xff0c;因为文件的内容多&#xff0c;这时候我们只需要把文件内容转成图片就可以解决这一问题&#xff0c;想要使用哪部分…

手把手带你开发你的第一个前端脚手架

开发一个简单的脚手架 1.创建 npm 项目 首先创建一个文件夹&#xff0c;然后进入到该文件夹目录下&#xff0c;执行 npm init -y 2.创建脚手架入口文件bin/index.js&#xff0c;在index.js中添加如下代码 #!/usr/bin/env nodeconsole.log(hello cli) 3.配置 package.json&a…

YOLOv5如何训练自己的数据集

目录 一、标注 1.1 标注软件下载labelimg 下载地址&#xff1a;mirrors / tzutalin / labelimg GitCode 1.2 json转txt 1.3 xml转txt 二、修改配置文件 2.1 建立文件目录 2.2 修改wzry_parameter.yaml文件 三、开始训练 3.1 2.结果 四、识别检测detect.py 1.调参找…

Jetson NX系统烧录以及CUDA、cudnn、pytorch等环境的安装

安装虚拟机和Ubuntu18.04环境 这两步比较简单&#xff0c;所以略了。虚拟机的配置需要注意硬盘空间大一点&#xff0c;至少40G。 安装sdk-manager NVIDIA SDK Manager下载地址&#xff1a;https://developer.nvidia.com/drive/sdk-manager sudo dpkg -i sdkmanager_1.9.0-…

YOLOv5和YOLOv7环境(GPU)搭建测试成功

本来是用doc写的&#xff0c;直接复制到这里很多图片加载缓慢&#xff0c;我直接把doc上传到资源里面了&#xff0c;0积分下载&#xff1a; (10条消息) YOLOv5和YOLOv7开发环境搭建和demo运行-Python文档类资源-CSDN文库 一、环境搭建 1.1 环境搭建参考链接 YOLO实践应用之…

uni-app 超详细教程(一)(从菜鸟到大佬)

一&#xff0c;uni-app 介绍 &#xff1a; 官方网页 uni-app 是一个使用 Vue.js 开发所有前端应用的框架&#xff0c;开发者编写一套代码&#xff0c;可发布到iOS、Android、Web&#xff08;响应式&#xff09;、以及各种小程序&#xff08;微信/支付宝/百度/头条/飞书/QQ/快手…

百度集团副总裁吴甜发布文心大模型最新升级,AI应用步入新阶段

11月30日&#xff0c;由深度学习技术与应用国家工程研究中心主办、百度飞桨承办的WAVE SUMMIT2022深度学习开发者峰会如期举行。百度集团副总裁、深度学习技术及应用国家工程研究中心副主任吴甜带来了文心大模型的最新升级&#xff0c;包括新增11个大模型&#xff0c;大模型总量…

PyQt5_寻找顶(底)背离并可视化

技术指标的背离是指技术指标曲线的波动方向与价格曲线的趋势方向不一致&#xff0c;是使用技术指标最为重要的一点。在股市中&#xff0c;常见的技术指标的背离分为两种常见的形式&#xff0c;即顶背离和底背离。背离是预示市场走势即将见顶或者见底的依据&#xff0c;在价格还…

计算机组成原理习题课第四章-1(唐朔飞)

计算机组成原理习题课第四章-1&#xff08;唐朔飞&#xff09; ✨欢迎关注&#x1f5b1;点赞&#x1f380;收藏⭐留言✒ &#x1f52e;本文由京与旧铺原创&#xff0c;csdn首发&#xff01; &#x1f618;系列专栏&#xff1a;java学习 &#x1f4bb;首发时间&#xff1a;&…