文章目录

  • 需求
  • 实现

需求

需求: 假设有10个线程,最多同时运行5个
要求: 不使用线程池,使用synchronized-wait&notifyAll机制


实现

详见注释

package com.artisan.test;import java.time.LocalTime;
import java.util.*;/*** 需求: 假设有10个线程,最多同时运行5个* 要求: 不使用线程池,使用synchronized-wait&notifyAll机制*/
public class ExerciseDemo {// 锁 Monitorprivate static final LinkedList<Control>  CONTROLLIST = new LinkedList();// 同时运行的最大线程数private static final int MAX_THREADS = 5;/*** 创建线程* @param threadName 线程名称* @return*/public static Thread createWorkThread(String threadName){return new Thread(() ->{// 加锁synchronized (CONTROLLIST){Optional.of(Thread.currentThread().getName() + " GOT LOCK ,BEGIN..." + LocalTime.now().withNano(0)).ifPresent(System.out::println);// 使用while// 当集合中运行的线程数量大于5时,wait,放弃锁,不执行while (CONTROLLIST.size() >= MAX_THREADS){try {Optional.of(Thread.currentThread().getName() + " WAIT").ifPresent(System.out::println);CONTROLLIST.wait();} catch (InterruptedException e) {e.printStackTrace();}}// 加入到LinkedList最后CONTROLLIST.addLast(new Control());}//模拟每个线程的业务,假设需要10秒才能结束Optional.of(Thread.currentThread().getName() + " working..." + LocalTime.now().withNano(0)).ifPresent(System.out::println);try {Thread.sleep(10_000);} catch (InterruptedException e) {e.printStackTrace();}// 输出业务完成Optional.of(Thread.currentThread().getName() + " END..." + LocalTime.now().withNano(0)).ifPresent(System.out::println);// 加锁synchronized (CONTROLLIST){// 移除最上面的线程CONTROLLIST.removeFirst();// 唤醒其他所有等待的线程CONTROLLIST.notifyAll();}},threadName);}/*** 主流程* @param args*/public static void main(String[] args) {List<Thread> workers  = new ArrayList();Arrays.asList("T1","T2","T3","T4","T5","T6","T7","T8","T9","T10").stream().map(ExerciseDemo::createWorkThread).forEach(t->{// 启动线程t.start();// 加入到集合列表,待后续一起joinworkers.add(t);});// 比那里保存线程的集合,10个线程 joinworkers.stream().forEach(t -> {try {t.join();} catch (InterruptedException e) {e.printStackTrace();}});// 全部完成后,输出结束标识Optional.of("DONE").ifPresent(System.out::println);}/*** 没啥实质做用,仅仅是个控制标识*/static class  Control{}}

运行日志

"E:\Program Files\Java\jdk1.8.0_161\bin\java" "-javaagent:E:\Program Files\JetBrains\IntelliJ IDEA 2017.2.4\lib\idea_rt.jar=60076:E:\Program Files\JetBrains\IntelliJ IDEA 2017.2.4\bin" -Dfile.encoding=UTF-8 -classpath "E:\Program Files\Java\jdk1.8.0_161\jre\lib\charsets.jar;E:\Program Files\Java\jdk1.8.0_161\jre\lib\deploy.jar;E:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\access-bridge-64.jar;E:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\cldrdata.jar;E:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\dnsns.jar;E:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jaccess.jar;E:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jfxrt.jar;E:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\localedata.jar;E:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\nashorn.jar;E:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunec.jar;E:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunjce_provider.jar;E:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunmscapi.jar;E:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunpkcs11.jar;E:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\zipfs.jar;E:\Program Files\Java\jdk1.8.0_161\jre\lib\javaws.jar;E:\Program Files\Java\jdk1.8.0_161\jre\lib\jce.jar;E:\Program Files\Java\jdk1.8.0_161\jre\lib\jfr.jar;E:\Program Files\Java\jdk1.8.0_161\jre\lib\jfxswt.jar;E:\Program Files\Java\jdk1.8.0_161\jre\lib\jsse.jar;E:\Program Files\Java\jdk1.8.0_161\jre\lib\management-agent.jar;E:\Program Files\Java\jdk1.8.0_161\jre\lib\plugin.jar;E:\Program Files\Java\jdk1.8.0_161\jre\lib\resources.jar;E:\Program Files\Java\jdk1.8.0_161\jre\lib\rt.jar;D:\IdeaProjects\mvc\target\classes" com.artisan.test.ExerciseDemo
T1 GOT LOCK ,BEGIN...00:03:41
T10 GOT LOCK ,BEGIN...00:03:41
T9 GOT LOCK ,BEGIN...00:03:41
T8 GOT LOCK ,BEGIN...00:03:41
T1 working...00:03:41
T7 GOT LOCK ,BEGIN...00:03:41
T8 working...00:03:41
T7 working...00:03:41
T10 working...00:03:41
T9 working...00:03:41
T6 GOT LOCK ,BEGIN...00:03:41
T6 WAIT
T5 GOT LOCK ,BEGIN...00:03:41
T5 WAIT
T4 GOT LOCK ,BEGIN...00:03:41
T4 WAIT
T3 GOT LOCK ,BEGIN...00:03:41
T3 WAIT
T2 GOT LOCK ,BEGIN...00:03:41
T2 WAIT
T10 END...00:03:51
T8 END...00:03:51
T2 working...00:03:51
T4 WAIT
T3 working...00:03:51
T5 WAIT
T6 WAIT
T1 END...00:03:51
T6 working...00:03:51
T5 WAIT
T4 WAIT
T9 END...00:03:51
T4 working...00:03:51
T5 WAIT
T7 END...00:03:51
T5 working...00:03:51
T2 END...00:04:01
T3 END...00:04:01
T6 END...00:04:01
T4 END...00:04:01
T5 END...00:04:01
DONEProcess finished with exit code 0
  1. 首先主线程中 初始化10个线程,分别命名为T1 … T10,先把这10个线程临时存放到集合

  2. 遍历集合,分别join . 不能在上一步的地方join , 这样的话就只能一个线程 一个线程的执行了(join会阻塞当前线程)

  3. 10个线程全部完成后,打印DONE

  4. 完成主要部分的编码后,就需要关注thread具体的业务逻辑了 : 定义一个锁 LinkedList<Control> ,当线程获取到锁,就将Control添加到Monitor中,如果大于规定的线程数,则wait

  5. 业务部分并行执行,当一个线程完成后,获取锁,从Monitor中移除一个Control, 然后notifyAll所有正在等待的线程

符合需求 ,OK

高并发编程-线程生产者消费者的综合示例相关推荐

  1. 高并发编程之生产者—消费者设计模式

    一.生产者-消费者模式介绍 生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题.生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接 ...

  2. 高并发编程-线程通信_使用wait和notify进行线程间的通信2_多生产者多消费者导致程序假死原因分析

    文章目录 概述 jstack或者可视化工具检测是否死锁(没有) 原因分析 概述 高并发编程-线程通信_使用wait和notify进行线程间的通信 - 遗留问题 我们看到了 应用卡住了 .... 怀疑是 ...

  3. Java并发编程实战~生产者-消费者模式

    前面我们在<Worker Thread 模式>中讲到,Worker Thread 模式类比的是工厂里车间工人的工作模式.但其实在现实世界,工厂里还有一种流水线的工作模式,类比到编程领域,就 ...

  4. 并发编程——进程——生产者消费者模型

    一.生产者消费者模型介绍 为什么要使用生产者消费者模型 生产者指的是生产数据的任务,消费者指的是处理数据的任务. 在并发编程中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者 ...

  5. 多线程-并发编程(7)-生产者消费者模式及非阻塞队列与阻塞队列实现

    生产者消费者模式是一个十分经典的多线程协作模式 弄懂生产者消费者问题能够让我们对多线程编程的理解更加深刻 存在3个元素 1.生产者(类比厨师) 2.生产者的生产产品(类比美食) 3.消费者(类比吃货) ...

  6. 高并发编程-线程通信_使用wait和notify进行线程间的通信

    文章目录 概述 场景 引子 synchronized wait/notify机制 synchronized wait/notify 改造 问题 概述 Java中线程通信协作的最常见的两种方式: syn ...

  7. 高并发编程-使用wait和notifyAll进行线程间的通信3_多线程下的生产者消费者模型和notifyAll

    文章目录 概述 解决办法 概述 高并发编程-线程通信_使用wait和notify进行线程间的通信2_多生产者多消费者导致程序假死原因分析 中分析了假死的原因,这里我们来看下改如何解决在多线程下出现的这 ...

  8. Java高并发编程详解系列-Java线程入门

    根据自己学的知识加上从各个网站上收集的资料分享一下关于java高并发编程的知识点.对于代码示例会以Maven工程的形式分享到个人的GitHub上面.   首先介绍一下这个系列的东西是什么,这个系列自己 ...

  9. libevent c++高并发网络编程_高并发编程学习(2)——线程通信详解

    前序文章 高并发编程学习(1)--并发基础 - https://www.wmyskxz.com/2019/11/26/gao-bing-fa-bian-cheng-xue-xi-1-bing-fa-j ...

最新文章

  1. 莫言:不要在不喜欢你的人那丢掉快乐
  2. JavaScript 技术篇-js只获取本节点text文本,不包含子节点
  3. 冲杯咖啡,谈谈计算机cpu
  4. 最新翻译的官方PyTorch简易入门教程(PyTorch1.0版本)
  5. 一篇能加深理解linux 虚拟文件系统的博文
  6. php 与 python对接_关于PHP调用Python的实施以及配置
  7. matlab实现一/多元线性回归
  8. Ubuntu下超实用的命令
  9. ASA站点×××,远程站点通过主站上网之配置
  10. 水电缴费系统php源码_php简易扫码付教育收费系统 v1.2
  11. oracle异步sql,Oracle sqlplus登陆异步io错误
  12. Ghost 备份、还原使用图解,带下载
  13. 第二十四讲 一阶常微分方程组
  14. 今天讲一下完整的前端模块化,很实用
  15. 基于STM32的ESP8266获取心知天气数据
  16. 手机卡顿?可能是你没关闭这两个选项(小米手机为例)
  17. 一键抠图Portrait Matting人像抠图 (C++和Android源码)
  18. Octapharma Group公布强劲的2018年业绩
  19. 2021年适合做什么行业?有发展前景的行业
  20. springboot 进阶

热门文章

  1. c++ 纯虚函数和抽象类那些事(一)
  2. crontab 运行pyhon脚本
  3. python3是unicode还是utf-8_ASCII、Unicode、UTF-8以及Python3编码问题
  4. 83. Leetcode 148. 排序链表 (排序)
  5. Leetcode 33.搜索旋转排序数组 (每日一题 20210707)
  6. 【转载】深度学习数学基础(二)~随机梯度下降(Stochastic Gradient Descent, SGD)
  7. 生物计算:SIR模型笔记
  8. 深度学习核心技术精讲100篇(二十)-如何通过树模型实现梯度提升树(GBDT)+LR,随机森林(RandomForest) +LR
  9. Python Generators(生成器)——yield关键字
  10. map初始化_需要掌握的Go基础之map:文末附面试题一道