两种方式实现线程通信:三个线程交替打印AABBCC
多线程之间是抢占资源的,使用线程通信可以达到线程按序执行的目的
线程共享资源类, 首先创建一个资源类, 包含三个打印的方法以及首次打印的字符串
多个线程访问,方法加synchronized同步锁
class Resource {String currentPrint = "AA"; // 初始打印,打印之后赋值为下一个要打印的内容/*** 打印AA* @param next 下一个要打印的字符串* @throws InterruptedException*/public synchronized void printAA(String next) throws InterruptedException {// 不是要打印的内容, 阻塞线程while (!Objects.equals(currentPrint, "AA")) {wait();}for (int i = 0; i < 3; i++) {System.out.println(Thread.currentThread().getName() + ": AA");}currentPrint= next;// 唤醒其他线程notifyAll();}/*** 打印BB* @param next 下一个要打印的字符串* @throws InterruptedException*/public synchronized void printBB(String next) throws InterruptedException {// 不是要打印的内容, 阻塞线程while (!Objects.equals(currentPrint, "BB")) {wait();}for (int i = 0; i < 3; i++) {System.out.println(Thread.currentThread().getName() + ": BB");}currentPrint= next;// 唤醒其他线程notifyAll();}/*** 打印CC* @throws InterruptedException*/public synchronized void printCC() throws InterruptedException {// 不是要打印的内容, 阻塞线程while (!Objects.equals(currentPrint, "CC")) {wait();}for (int i = 0; i < 3; i++) {System.out.println(Thread.currentThread().getName() + ": CC");}}
}
创建线程执行程序进行交替打印
public class AABBCC {public static void main(String[] args) {ThreadPoolExecutor threadPoolExecutor = null;try {// 创建一个最大长度为3的线程池threadPoolExecutor = new ThreadPoolExecutor(3, 3, 0,TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>(10), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());Resource resource = new Resource();// 将要执行的任务插入到集合中List<Runnable> list = new ArrayList<>();list.add(()->{try { resource.printAA("BB"); } catch (InterruptedException e) { e.printStackTrace(); }});list.add(()->{try { resource.printBB("CC"); } catch (InterruptedException e) { e.printStackTrace(); }});list.add(()->{try { resource.printCC();} catch (InterruptedException e) {e.printStackTrace();}});for (int i = 0; i < list.size(); i++) {threadPoolExecutor.execute(list.get(i));}} catch (Exception e) {e.printStackTrace();} finally {// 关闭线程池if (threadPoolExecutor != null) {threadPoolExecutor.shutdown();}}}
}
执行结果
资源类冗余代码进行优化
/*** 打印字符串* @param currentPrintParam 当前* @param next 下一个* @param times 打印次数* @throws InterruptedException*/public synchronized void printStr(String currentPrintParam,String next, int times) throws InterruptedException {// 不是要打印的内容, 阻塞线程while (!Objects.equals(currentPrint, currentPrintParam)) {wait();}for (int i = 0; i < times; i++) {System.out.println(Thread.currentThread().getName() + ": "+ currentPrint);}currentPrint = next;// 唤醒其他线程notifyAll();}
调用方法替换
Resource resource = new Resource();// 将要执行的任务插入到集合中List<Runnable> list = new ArrayList<>();list.add(()->{try { resource.printStr("AA", "BB", 3); } catch (InterruptedException e) { e.printStackTrace(); }});list.add(()->{try { resource.printStr("BB", "CC", 3); } catch (InterruptedException e) { e.printStackTrace(); }});list.add(()->{try { resource.printStr("CC", "", 3);} catch (InterruptedException e) {e.printStackTrace();}});for (int i = 0; i < list.size(); i++) {threadPoolExecutor.execute(list.get(i));}
执行结果
JDK5在java.util.concurrent包下提供了Lock并发锁
资源类代码新增
Lock lock = new ReentrantLock(); // 并发锁Condition aCondition = lock.newCondition();Condition bCondition = lock.newCondition();Condition cCondition = lock.newCondition();/*** 打印字符串* @param currentPrintParam 当前线程打印* @param nextPrint 下一个线程打印* @param currentCondition 当前线程* @param nextCondition 下一个线程* @param times 打印次数* @throws InterruptedException*/public void lockPrintStr(String currentPrintParam, String nextPrint, Condition currentCondition, Condition nextCondition, int times) {lock.lock();try {// 不是要打印的内容 阻塞线程while (!Objects.equals(currentPrint, currentPrintParam)) {currentCondition.await();}for (int i = 0; i < times; i++) {System.out.println(Thread.currentThread().getName() + ": "+ currentPrint);}currentPrint = nextPrint;// 唤醒下一个打印条件的线程if (!Objects.isNull(nextCondition)) {nextCondition.signal();}} catch (Exception e) {e.printStackTrace();} finally {// 释放锁if (lock != null) {lock.unlock();}}}
调用新增的方法
Resource resource = new Resource();// 将要执行的任务插入到集合中List<Runnable> list = new ArrayList<>();list.add(()->{resource.lockPrintStr("AA", "BB", resource.aCondition, resource.bCondition, 3);});list.add(()->{resource.lockPrintStr("BB", "CC", resource.bCondition, resource.cCondition, 3);});list.add(()->{resource.lockPrintStr("CC", "", resource.cCondition, null, 3);});for (int i = 0; i < list.size(); i++) {threadPoolExecutor.execute(list.get(i));}
执行结果
多次执行的结果中可以看出,由三个线程交替打印AABBCC
总结:
- 线程通信其中两种方式 Object类下wait()、notify()/notifyAll(),以及JDK5以后提供的Lock下Condition内部类的await()、signal()方法。
- 使用wait/notifyAll进行线程通信唤醒唤醒了所有线程,增加了上下文的切换时间,使用await/signal可以实现精准唤醒,java集合框架中的队列就采用了后者实现线程通信
两种方式实现线程通信:三个线程交替打印AABBCC相关推荐
- 7 并发编程-(线程)-开启线程的两种方式
thread/英 /θred/ 美 /θrɛd/ 线程 1.threading模块介绍 multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性,因而不再 ...
- 19、Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition
Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...
- 线程间协作的两种方式:wait、notify、notifyAll和Condition
转载自 线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者模型:当 ...
- linux的进程与库之间的通信两种方式
文章目录 前言 一.进程A与算法库b的通信方式之一:动态dlopen加载算法库b,编译的时候是需要加载该头文件就可以,无需连接该算法库b 具体的实施细节: 二.进程A与算法库b的通信方式之二:进程A编 ...
- Java中线程的创建有两种方式
Java中继承thread类与实现Runnable接口的区别 Java中线程的创建有两种方式: 1. 通过继承Thread类,重写Thread的run()方法,将线程运行的逻辑放在其中 2. 通过 ...
- python创建多线程_Python 多线程,threading模块,创建子线程的两种方式示例
本文实例讲述了Python 多线程,threading模块,创建子线程的两种方式.分享给大家供大家参考,具体如下: GIL(全局解释器锁)是C语言版本的Python解释器中专有的,GIL的存在让多线程 ...
- java创建线程的两种方式及区别
本文将介绍创建线程的两种方式,示例代码在下面,复制粘贴即可 继承Thread类方式和实现Runnable接口方式 区别:由于在开发的过程中,很多的类都会用到继承的方式,如果采用继承的方式会让各个类之间 ...
- java匿名启动线程_使用匿名内部类:来创建线程的两种方式
[Java]基础31:创建线程的两种方式 谢谢你的观看. 今天是我自学Java的第31天. 你的观看便是对我最大的鼓励. 话不多说,开始今天的学习: 线程的创建有两种方式,昨天学习过其中的一种: 创建 ...
- Java并发基础01. 传统线程技术中创建线程的两种方式
传统的线程技术中有两种创建线程的方式:一是继承Thread类,并重写run()方法:二是实现Runnable接口,覆盖接口中的run()方法,并把Runnable接口的实现扔给Thread.这两种方式 ...
最新文章
- 【青少年编程】【一级】舞者凯希
- linux中如何清空一个文件的内容
- linux php5.3 ssh2,Linux 安装php 的 ssh2扩展
- scrapy-redis 分布式哔哩哔哩网站用户爬虫
- [Java基础]Arrays的常用方法
- Nginx的TCP运行时健康检查
- 视频数据:骨骼数据采集(Skeleton Data)
- Java中常见RuntimeException与其他异常表及Exception逻辑关系详解
- NHibernate 基础
- Atitit web httphandler的实现 java python node.js c# net php 目录 1.1. Java 过滤器 servelet	1 1.2. Python的
- 只安装mysql客户端_单独安装mysql客户端
- C语言实现哈夫曼树求解及其编码输出
- 使用helm部署kubeapps
- 10月12日 阅读数异常公告
- Psychopy | 第2期:从Stroop看条件与循环
- Python学习基础方便查询
- PCIE--1--概念认知
- 圣商,牢记使命成就当代圣商
- Python学习-操作列表
- Magix 促销:让你的音视频制作更加专业
热门文章
- Tf2.0+基于注意力的神经机器翻译训练发布过程
- correl函数_WPS表格办公— CORREL 函数的用法
- 鼠标经过爆炸效果html,jquery鼠标滑过爆炸特效插件
- 爬虫学习经验分享-------某点评网站
- 攻略:手把手教你如何看懂以太坊区块链浏览器(配图更清晰)
- Excel提取单元格中的数字
- 红米Android降级,红米Note 5(安卓9.0 不要降级刷低版本)纯净ROOT线刷包分享,一键救砖教程,轻松刷回官方系统,流畅如初!...
- 几个python运维脚本
- vim 删除行首和行尾空格
- 部署 docker 容器虚拟化平台