多线程打印

1、固定运行顺序

比如,必须先 2 后 1 打印

1.1、wait notify 版
public class Test1 {// 先打印2,后打印1static final Object lock = new Object();static boolean t2runned = false;  //表示t2是否运行过public static void main(String[] args) {Thread t1 = new Thread(()->{synchronized (lock){while(!t2runned){try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}}System.out.println(Thread.currentThread().getName() + ": " + "1");}, "t1");Thread t2 = new Thread(()->{synchronized (lock) {System.out.println(Thread.currentThread().getName() + ": " + "2");t2runned = true;lock.notifyAll();}}, "t2");t1.start();t2.start();}
}
1.2、Park Unpark 版

可以看到,实现上很麻烦:
● 首先,需要保证先 wait 再 notify,否则 wait 线程永远得不到唤醒。因此使用了『运行标记』来判断该不该 wait 。
● 第二,如果有些干扰线程错误地 notify 了 wait 线程,条件不满足时还要重新等待,使用了 while 循环来解决 此问题。
● 最后,唤醒对象上的 wait 线程需要使用 notifyAll,因为『同步对象』上的等待线程可能不止一个
可以使用 LockSupport 类的 park 和 unpark 来简化上面的题目:

import java.util.concurrent.locks.LockSupport;public class Test2 {public static void main(String[] args) {Thread t1 = new Thread(()->{LockSupport.park();System.out.println(Thread.currentThread().getName() + ": " + "1");},"t1");t1.start();Thread t2 = new Thread(()->{System.out.println(Thread.currentThread().getName() + ": " + "2");LockSupport.unpark(t1);},"t2");t2.start();}
}

2、交替打印abc

线程 1 输出 a 5 次,线程 2 输出 b 5 次,线程 3 输出 c 5 次。现在要求输出 abcabcabcabcabc 怎么实现

2.1 wait notify 版
public class Test3 {public static void main(String[] args) {WaitNotify wt = new WaitNotify(1, 5);new Thread(()->{wt.print("a", 1, 2);}).start();new Thread(()->{wt.print("b", 2, 3);}).start();new Thread(()->{wt.print("c", 3, 1);}).start();}
}/*
输出内容    等待标记    下一个标记a          1           2b          2           3c          3           1
*/
class  WaitNotify{// 打印                    a         1              2public void print(String str, int waitFlag, int nextFlag){for (int i = 0; i < loopNumber; i++) {synchronized (this){while(waitFlag != flag)try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.print(str);flag = nextFlag;this.notifyAll();}}}private int flag;       //等待标记  1private int loopNumber; //循环次数public WaitNotify(int flag, int loopNumber) {this.flag = flag;this.loopNumber = loopNumber;}
}

3、交替打印奇偶数

两个线程交替打印0~100的奇偶数
● 偶线程:0
● 奇线程:1
● 偶线程:2

3.1、synchronized实现

缺点:效率低,会出现浪费的竞争。比如说,一直是偶数线程拿到锁,进行判断后不满足条件,就不会去执行打印语句,然后跳出,这样的话很多次竞争拿到锁是没有意义的。

import com.sun.javaws.IconUtil;/*
两个线程交替打印0~100的奇偶数,用synchronized关键字实现*/
public class WaitNotifyPrintOddEvenSyn {private static int count;private static final Object lock = new Object();//新建两个线程//1个只处理偶数,第二个只处理奇数(用位运算)//用synchronized来通信public static void main(String[] args) {new Thread( ()->{while(count < 100){synchronized (lock){if((count & 1) == 0){System.out.println(Thread.currentThread().getName() + ":" + count++);}}}}, "偶数").start();new Thread(()->{while(count < 100){synchronized (lock){if((count & 1) == 1){System.out.println(Thread.currentThread().getName() + ":" + count++);}}}}, "奇数").start();}
}
3.2、wait/notify

优点:效率高,一个线程拿到锁就去打印,打印完,唤醒其他线程,自己就休眠,每次的竞争都是有意义的。

import javax.sound.sampled.FloatControl;
/*两个线程交替打印0~100的奇偶数,用wait/notify实现*/
public class WaitNotifyPrintOddEvenWait {private static  int count = 0;private static Object lock = new Object();public static void main(String[] args) throws InterruptedException {new Thread(new TurningRunner(), "偶数").start();Thread.sleep(100);new Thread(new TurningRunner(), "奇数").start();}// 1.拿到锁,我们就打印// 2.打印完,唤醒其他线程,自己就休眠static class TurningRunner implements Runnable{@Overridepublic void run() {while(count <= 100){synchronized (lock){// 拿到锁就打印System.out.println(Thread.currentThread().getName() + ":" + count++);lock.notify();if(count <= 100){// 如果任务还没结束,就让出当期的锁,并休眠try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}}}}}
}

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

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

相关文章

流程的控制

条件选择语句 我们一般将条件选择语句分为三类&#xff1a; 单条件双条件多条件 本篇文章将分开诉说着三类。 单条件 单条件的语法很简单&#xff1a; if (条件) {// 代码}条件这里我们需要注意下&#xff0c;可以向里写入两种&#xff1a; 布尔值布尔表达式 当然&…

Docker高级篇之Docker网络

文章目录 1. Docker Network简介2. Docker 网络模式3. Docker 网络模式之bridge4. Docker 网络模式之host5. Docker 网络模式之none6. Docker 网络模式之container7. Docker 网络模式之自定义网络模式 1. Docker Network简介 从Docker的架构和运作流程来看&#xff0c;Docker是…

C语言中函数的参数传递机制(值传递、指针传递)

在C语言中&#xff0c;函数的参数传递机制主要有两种&#xff1a;值传递&#xff08;Pass by Value&#xff09;和指针传递&#xff08;Pass by Reference&#xff0c;虽然C语言中没有直接的“Pass by Reference”这一术语&#xff0c;但通常使用指针来实现类似的效果&#xff…

计算机组成原理之指令寻址

一、顺序寻址 1、定长指令字结构 2、变长指令字结构 二、跳跃寻址 三、数据寻址 1、直接寻址 2、间接寻址 3、寄存器寻址 寄存器间接寻址 4、隐含寻址 5、立即寻址 6、偏移寻址 1、基址寻址 2、变址寻址 3、相对寻址

力扣199. 二叉树的右视图

给定一个二叉树的 根节点 root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 示例 1: 输入: [1,2,3,null,5,null,4] 输出: [1,3,4]示例 2: 输入: [1,null,3] 输出: [1,3]示例 3: 输入: [] 输出: [] /*** Def…

纸片战争(信息课神器,断网也可以玩)

作品简介及操作说明 作品介绍&#xff1a; 游戏背景&#xff1a; 阿尔法国遭到了厄普西隆国的入侵。为了保卫祖国&#xff0c;阿尔法人迅速组织部队进行抗争&#xff0c;而你&#xff0c;将作为阿尔法人的指挥官亲历这场战争。 玩法类似游戏《红色警戒》&#xff0c;指挥部队、…

Spring 怎么解决循环依赖的问题?

Spring框架解决循环依赖主要通过三级缓存来实现&#xff0c;这主要发生在Spring容器创建bean的过程中。以下是Spring解决循环依赖的基本步骤&#xff1a; 一级缓存&#xff08;singletonObjects&#xff09;&#xff1a;存放已经创建好的单例对象&#xff0c;供其他bean引用。 …

语法分析!!!

一、实验题目 根据给定文法编写调试预测分析程序&#xff0c;对任意输入串用预测分析法进行语法分析。 二、实验目的 加深对预测分析法的理解。 三、实验内容 四、实验代码 #include <iostream> #include <stdio.h> #include <string> #include <…

隐式链接DLL

本文仅供学习交流&#xff0c;严禁用于商业用途&#xff0c;如本文涉及侵权请及时联系本人将于及时删除 【例9.5】创建的基于MFC对话框的应用程序MFCImLink2&#xff0c;隐式链接例9.2创建的MFCLibrary2.dll&#xff0c;使用其中的导出函数求正方形的面积。 (1) 使用MFC应用程…

【零基础一看就会】Python爬虫从入门到应用(下)

目录 一、urllib的学习 1.1 urllib介绍 1.2 urllib的基本方法介绍 urllib.Request &#xff08;1&#xff09;构造简单请求 &#xff08;2&#xff09;传入headers参数 &#xff08;3&#xff09;传入data参数 实现发送post请求&#xff08;示例&#xff09; response.…

野火FPGA跟练(四)——串口RS232、亚稳态

目录 简介接口与引脚通信协议亚稳态RS232接收模块模块框图时序波形RTL 代码易错点Testbench 代码仿真 RS232发送模块模块框图时序波形RTL 代码Testbench 代码仿真 简介 UART&#xff1a;Universal Asynchronous Receiver/Transmitter&#xff0c;异步串行通信接口。发送数据时…

网络流媒体协议——RTMP

流媒体协议常用实时信息传输协议(Real-Time Messaging Protocol,RTMP)和 HLS 协议。RTMP 为应用层协议,由 TCP 提供传输层的连接和传输服务,默认端口为1935。 RTMP URL rtmp://host:port/app/steamrtmp∶ 表示该URL必须以RTMP进行解析。host, port 分别表示主机地址和端口…

微服务开发与实战Day04

一、网关路由 网关&#xff1a;就是网络的关口&#xff0c;负责请求的路由、转发、身份校验。 在SpringCloud中网关的实现包括两种&#xff1a; 1. 快速入门 Spring Cloud Gateway 步骤&#xff1a; ①新建hm-gateway模块 ②引入依赖pom.xml(hm-gateway) <?xml version…

解锁俄罗斯市场:如何选择优质的俄罗斯云服务器

在当前云计算市场上&#xff0c;很多大型的云厂商并没有俄罗斯服务器的云节点&#xff0c;这给许多企业在拓展海外业务时带来了一定的困扰。然而&#xff0c;俄罗斯作为一个经济发展迅速的国家&#xff0c;其市场潜力不可忽视。因此&#xff0c;选择一台优质的俄罗斯云服务器成…

【MySQL】(基础篇三) —— 创建数据库和表

管理数据库和表 管理数据库 创建数据库 在MySQL中&#xff0c;创建数据库的SQL命令相对简单&#xff0c;基本语法如下&#xff1a; CREATE DATABASE 数据库名;如果你想避免在尝试创建已经存在的数据库时出现错误&#xff0c;可以添加 IF NOT EXISTS 子句&#xff0c;这样如…

04-4.1.2 串的存储结构

&#x1f44b; Hi, I’m Beast Cheng&#x1f440; I’m interested in photography, hiking, landscape…&#x1f331; I’m currently learning python, javascript, kotlin…&#x1f4eb; How to reach me --> 458290771qq.com 喜欢《数据结构》部分笔记的小伙伴可以订…

数据结构(C):二叉树前中后序和层序详解及代码实现及深度刨析

目录 &#x1f31e;0.前言 &#x1f688;1.二叉树链式结构的代码是实现 &#x1f688;2.二叉树的遍历及代码实现和深度刨析代码 &#x1f69d;2.1前序遍历 ✈️2.1.1前序遍历的理解 ✈️2.1.2前序代码的实现 ✈️2.1.3前序代码的深度解剖 &#x1f69d;2.2中序遍历 ✈…

Spring boot SSL证书路径配置

SSL证书路径配置: 1、打包到resouce下&#xff1a; server:port: 443ssl:enabled: truekey-store: classpath:XX.XX.com.p12key-store-password: your-passwordkeyStoreType: PKCS12keyAlias: your-alias 2、放到windows类型服务器硬盘上 Windows系统中&#xff0c;由于路径…

一些常用的frida脚本

这里整理一些常用的frida脚本&#xff0c;和ghidra 一起食用风味更佳&#xff5e; Trace RegisterNatives 注意到从java到c的绑定中&#xff0c;可能会在JNI_OnLoad动态的执行RegisterNatives方法来绑定java层的函数到c行数&#xff0c;可以通过这个方法&#xff0c;来吧运行…

VSCode 1.90版本 升级需谨慎~(Python)

由于再次出现justMyCode的问题&#xff0c;请使用Python的小伙伴要谨慎将Visual Studio Code升级到1.90版本&#xff08;两天前官方刚发布的&#xff09; 若已经升级到1.90的小伙伴&#xff0c;可以从这里下载1.89版本进行“补救“&#xff1a; 1.89.1版本下载链接&#xff1a;…