多线程之间是抢占资源的,使用线程通信可以达到线程按序执行的目的

线程共享资源类, 首先创建一个资源类, 包含三个打印的方法以及首次打印的字符串
多个线程访问,方法加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

总结:

  1. 线程通信其中两种方式 Object类下wait()、notify()/notifyAll(),以及JDK5以后提供的Lock下Condition内部类的await()、signal()方法。
  2. 使用wait/notifyAll进行线程通信唤醒唤醒了所有线程,增加了上下文的切换时间,使用await/signal可以实现精准唤醒,java集合框架中的队列就采用了后者实现线程通信

两种方式实现线程通信:三个线程交替打印AABBCC相关推荐

  1. 7 并发编程-(线程)-开启线程的两种方式

    thread/英 /θred/ 美 /θrɛd/  线程 1.threading模块介绍 multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性,因而不再 ...

  2. 19、Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition

    Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...

  3. 线程间协作的两种方式:wait、notify、notifyAll和Condition

    转载自  线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者模型:当 ...

  4. linux的进程与库之间的通信两种方式

    文章目录 前言 一.进程A与算法库b的通信方式之一:动态dlopen加载算法库b,编译的时候是需要加载该头文件就可以,无需连接该算法库b 具体的实施细节: 二.进程A与算法库b的通信方式之二:进程A编 ...

  5. Java中线程的创建有两种方式

    Java中继承thread类与实现Runnable接口的区别 Java中线程的创建有两种方式: 1.  通过继承Thread类,重写Thread的run()方法,将线程运行的逻辑放在其中 2.  通过 ...

  6. python创建多线程_Python 多线程,threading模块,创建子线程的两种方式示例

    本文实例讲述了Python 多线程,threading模块,创建子线程的两种方式.分享给大家供大家参考,具体如下: GIL(全局解释器锁)是C语言版本的Python解释器中专有的,GIL的存在让多线程 ...

  7. java创建线程的两种方式及区别

    本文将介绍创建线程的两种方式,示例代码在下面,复制粘贴即可 继承Thread类方式和实现Runnable接口方式 区别:由于在开发的过程中,很多的类都会用到继承的方式,如果采用继承的方式会让各个类之间 ...

  8. java匿名启动线程_使用匿名内部类:来创建线程的两种方式

    [Java]基础31:创建线程的两种方式 谢谢你的观看. 今天是我自学Java的第31天. 你的观看便是对我最大的鼓励. 话不多说,开始今天的学习: 线程的创建有两种方式,昨天学习过其中的一种: 创建 ...

  9. Java并发基础01. 传统线程技术中创建线程的两种方式

    传统的线程技术中有两种创建线程的方式:一是继承Thread类,并重写run()方法:二是实现Runnable接口,覆盖接口中的run()方法,并把Runnable接口的实现扔给Thread.这两种方式 ...

最新文章

  1. 【青少年编程】【一级】舞者凯希
  2. linux中如何清空一个文件的内容
  3. linux php5.3 ssh2,Linux 安装php 的 ssh2扩展
  4. scrapy-redis 分布式哔哩哔哩网站用户爬虫
  5. [Java基础]Arrays的常用方法
  6. Nginx的TCP运行时健康检查
  7. 视频数据:骨骼数据采集(Skeleton Data)
  8. Java中常见RuntimeException与其他异常表及Exception逻辑关系详解
  9. NHibernate 基础
  10. Atitit web httphandler的实现 java python node.js c# net php 目录 1.1. Java 过滤器 servelet 1 1.2. Python的
  11. 只安装mysql客户端_单独安装mysql客户端
  12. C语言实现哈夫曼树求解及其编码输出
  13. 使用helm部署kubeapps
  14. 10月12日 阅读数异常公告
  15. Psychopy | 第2期:从Stroop看条件与循环
  16. Python学习基础方便查询
  17. PCIE--1--概念认知
  18. 圣商,牢记使命成就当代圣商
  19. Python学习-操作列表
  20. Magix 促销:让你的音视频制作更加专业

热门文章

  1. Tf2.0+基于注意力的神经机器翻译训练发布过程
  2. correl函数_WPS表格办公— CORREL 函数的用法
  3. 鼠标经过爆炸效果html,jquery鼠标滑过爆炸特效插件
  4. 爬虫学习经验分享-------某点评网站
  5. 攻略:手把手教你如何看懂以太坊区块链浏览器(配图更清晰)
  6. Excel提取单元格中的数字
  7. 红米Android降级,红米Note 5(安卓9.0 不要降级刷低版本)纯净ROOT线刷包分享,一键救砖教程,轻松刷回官方系统,流畅如初!...
  8. 几个python运维脚本
  9. vim 删除行首和行尾空格
  10. 部署 docker 容器虚拟化平台