java线程基础巩固---线程生产者消费者的综合实战结合Java8语法
基于上一次【http://www.cnblogs.com/webor2006/p/8909558.html】学习的多个生产者与多个消费者模型,此次用另外一个案例来进一步巩固线程之间的调度处理,这里还是以之前【http://www.cnblogs.com/webor2006/p/7895410.html】举过的信息采集功能为例:有若干台采集服务器,然后还有一台主机,这台主机需要等待这若干台服务器信息采集完之后再做进一步的处理,一台采集服务器就对应一个线程,如之前写的代码:

但是假如有成千上万台那怎么办,不可能每台服务器对应一个线程,因为线程是有一个stackSize的上限滴,此时就需要用到线程同步来避勉这个问题了,比如:最大工作线程数就是5个,然后当超过5个的时候其它的工作线程都会进行wait()释放出cpu执行权,待有一个工作线程执行完了则通知wait()的其它线程加入工作队列,大体思路是这样,下面来看一下如何具体执行,这里采用Java8的语法来编写,毕境之前学习过练练手:
首先创建十个线程,这里采用流的方式来创建,如下:

好,具体线程的执行代码这里先放一放,先将框架代码编写好,因为需要等待每个线程的执行完成再执行,所以此时需要用到join()方法了,如下:

所以此时应该用一个集合将所有启动的线程给缓存下来,但是对于Java8中的Stream.forEach()方法是一个teminal operation,执行完流操作就结束了,所以这里定义一个集合变量准备来缓存一下:

然后接下来就可以进行join()总的操作了,如下:

好了~~框架搭建完毕!接下来就得将重心放在线程的具体执行这块了,如下:

接着线程执行前先要来判断是否工作线程数已经超过5个了,如果超过那其它所有线程都得wait()了,而如何判断工作线程总数呢?这里需要用一定的技巧,这里就不卖关子了,贴出来细细体会:
public class CaptureService {
private static final int MAX_WORKER = 5;
private static final LinkedList<CaptureService.Control> CONTROLS = new LinkedList<>();//代表总的工作线程
public static void main(String[] args) {
List<Thread> worker = new ArrayList<>();
Arrays.asList("M1", "M2", "M3", "M4", "M5", "M6", "M7", "M8", "M9", "M10").stream()
.map(CaptureService::createCaptureThread)
.forEach(t -> {
t.start();//启动每一个线程
worker.add(t);
});
worker.stream().forEach(t -> {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Optional.of("All of capture work finished").ifPresent(System.out::println);
}
private static Thread createCaptureThread(String name) {
return new Thread(() -> {
Optional.of("The worker [" + Thread.currentThread().getName() + "] BEGIN capture data").ifPresent(System.out::println);
synchronized (CONTROLS) {
while (CONTROLS.size() > MAX_WORKER) {
try {
Optional.of("The worker [" + Thread.currentThread().getName() + "] WAIT..").ifPresent(System.out::println);
CONTROLS.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
CONTROLS.addLast(new CaptureService.Control());
}
}, name);
}
private static class Control {
//nothing to do,just a tag
}
}
而如果不满足wait()条件的那当然就得正常工作喽,如下:

而当一个线程任务执行完,则需要通知其它还在wait()住的线程叫他们赶紧加入工作队列中,如下:

另外还得注意咱们是按先进先出的原则来添加tag的,如下:

好,至此代码写完,看一下运行结果:


java线程基础巩固---线程生产者消费者的综合实战结合Java8语法的更多相关文章
- Java阻塞队列(BlockingQueue)实现 生产者/消费者 示例
Java阻塞队列(BlockingQueue)实现 生产者/消费者 示例 本文由 TonySpark 翻译自 Javarevisited.转载请参见文章末尾的要求. Java.util.concurr ...
- Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量
Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量 一丶线程的理论知识 什么是线程: 1.线程是一堆指令,是操作系统调度 ...
- java线程之多个生产者消费者
温故一下上一节所学习的生产者消费者代码: 两个线程时: 通过标志位flag的if判断和同步函数互斥较好解决两个线程,一个生产者.一个消费者交替执行的功能 类名:ProducterConsumerDem ...
- 基于线程池的线程管理(BlockingQueue生产者消费者方式)实例
1.线程池管理类: public class ThreadPoolManager { private static ThreadPoolManager instance = new ThreadPoo ...
- python进阶:Python进程、线程、队列、生产者/消费者模式、协程
一.进程和线程的基本理解 1.进程 程序是由指令和数据组成的,编译为二进制格式后在硬盘存储,程序启动的过程是将二进制数据加载进内存,这个启动了的程序就称作进程(可简单理解为进行中的程序).例如打开一个 ...
- java线程基础巩固---线程间通信快速入门,使用wait和notify进行线程间的数据通信
之前已经对于线程同步相关的知识点进行了详细的学习,这次来学习一下线程间的通信相关的知识,话不多说直接用代码进行演练,以一个简陋的生产者消费者模型来初步了解下线程间通信是怎么一回事. 生产消费者第一版: ...
- java线程基础巩固---线程生命周期以及start方法源码剖析
上篇中介绍了如何启动一个线程,通过调用start()方法才能创建并使用新线程,并且这个start()是非阻塞的,调用之后立马就返回的,实际上它是线程生命周期环节中的一种,所以这里阐述一下线程的一个完整 ...
- Java并发基础:线程的创建
线程的创建和管理: 1.应用Thread类显式创建.管理线程 2.应用Executor创建并管理线程. 定义任务: 无返回的任务:实现Runnable接口并编写run()方法. 有响应的任务:实现Ca ...
- Java多线程之并发协作生产者消费者设计模式
两个线程一个生产者个一个消费者 需求情景 两个线程,一个负责生产,一个负责消费,生产者生产一个,消费者消费一个 涉及问题 同步问题:如何保证同一资源被多个线程并发访问时的完整性.常用的同步方法是采用标 ...
随机推荐
- PTA --- L1-002 打印沙漏
题目地址 本题要求你写个程序把给定的符号打印成沙漏的形状.例如给定17个“*”,要求按下列格式打印 ***** *** * *** ***** 所谓“沙漏形状”,是指每行输出奇数个符号:各行符号中心对 ...
- LeetCode.1207-唯一的元素出现次数(Unique Number of Occurrences)
这是小川的第次更新,第篇原创 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第269题(顺位题号是1207).给定一个整数数组arr,当且仅当该数组中每个元素的出现次数唯一时,返回tr ...
- Linux下测试ZLAN 5800
今天师兄让帮忙测试ZLAN 5800八串口通信模块,windows下的测试按照手册来已经搞定,接下来是Linux下的测试. 因为厂家不提供Linux下的相关资料,所以需要在windows下设置好后直接 ...
- [计蒜客T2237]魔法_树
魔法 题目大意: 数据范围: 题解: 这个题挺好玩的 可以用反证法,发现所有叶子必须都得选而且所有叶子都选了合法. 故此我们就是要使得,一次操作之后使得叶子的个数最少. 这怎么弄呢? 我们发现,如果一 ...
- DOS bcp
C:\>bcp /?用法: bcp {dbtable | query} {in | out | queryout | format} 数据文件 [-m 最大错误数] [ ...
- web应用安全
一.三种坏人与servlet安全 网络攻击者 对应的servlet安全规范 假冒者 认证 非法升级者 授权 窃听者 机密性 数据完整性 认证可以防止“假冒者”攻击,授权可以防止“非法升级者”攻击, ...
- Android控制UI界面
⒈使用XML布局文件控制UI界面[推荐] Android推荐使用XML布局文件来控制视图,这样不仅简单.明了,而且可以将应用的视图控制逻辑从Java或Kotlin代码中分离出来,放入XML文件中控制, ...
- COleVariant功能
COLeVariant是数据库常用到的数据类型.它可以是字符串,整型值,日期等.知道怎样将它转换为CString. COLeVariant类是对VARIANT结构的封装.它的构造函数具有极为强大的功能 ...
- matplotlib库绘制散点图
假设通过爬虫你获取到了北京2016年3,10月份每天白天的最高气温(分别位于列表a,b),那么此时如何寻找出气温随时间(天)变化的某种规律? a = [11,17,16,11,12,11,12,6,6 ...
- Win32汇编之其他指令
汇编语言(assembly language)是一种用于电子计算机.微处理器.微控制器或其他可编程器件的低级语言,亦称为符号语言.在汇编语言中,用助记符(Mnemonics)代替机器指令的操作码,用地 ...