JUC 并发编程--10, 阻塞队列之--LinkedBlockingDeque 工作窃取, 代码演示
直接上代码
class LinkedBlockingDequeDemo {
// 循环是否结束的开关
private static volatile boolean flag1 = true;
private static volatile boolean flag2 = true;
// 生成者生产的产品
private static AtomicInteger atomicInteger = new AtomicInteger(1);
//二个 双端阻塞队列
private LinkedBlockingDeque linkedBlockingDeque1;
private LinkedBlockingDeque linkedBlockingDeque2;
public LinkedBlockingDequeDemo(LinkedBlockingDeque linkedBlockingDeque1, LinkedBlockingDeque linkedBlockingDeque2) {
this.linkedBlockingDeque1 = linkedBlockingDeque1;
this.linkedBlockingDeque2 = linkedBlockingDeque2;
System.out.println(linkedBlockingDeque1.getClass().getName());
System.out.println(linkedBlockingDeque2.getClass().getName());
}
// 生产者
public void producer() throws InterruptedException {
String data = "";
while (flag1) {
data = atomicInteger.getAndIncrement() + "";//这是产品
//TimeUnit.SECONDS.sleep(1);// 1秒生成一个产品
if (Integer.valueOf(data) <= 10) {
//存到 linkedBlockingDeque1 队列中
linkedBlockingDeque1.put(data + "队列1");
System.out.println(Thread.currentThread().getName() + "添加元素到 阻塞队列 linkedBlockingDeque1,成功,元素为: " + data + "队列1");
} else {
//存到 linkedBlockingDeque2 队列中
linkedBlockingDeque2.put(data + "队列2");
System.out.println(Thread.currentThread().getName() + "添加元素到 阻塞队列 linkedBlockingDeque2,成功,元素为: " + data + "队列2");
}
}
}
// 消费者
public void consumer1() throws InterruptedException {
while (flag2) {
try {
TimeUnit.MILLISECONDS.sleep(3);
if (!linkedBlockingDeque1.isEmpty()) {
// 自己的队列不为空, 就从自己的队列中取数据消费, 从头开始消费数据
System.out.println(Thread.currentThread().getName() + "从自己队列 Deque1中 的头部消费了一个产品:" + linkedBlockingDeque1.takeFirst());
} else if (!linkedBlockingDeque2.isEmpty()) {
// 如果 另一个队列不为空, 就从他的尾开始消费数据
System.out.println(Thread.currentThread().getName() + "从别人队列 Deque2中 的尾部消费了一个产品:" + linkedBlockingDeque2.takeLast());
} else {
flag2 = false;//这里结束消费
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("------------------------------------------");
}
}
public void consumer2() throws InterruptedException {
while (flag2) {
try {
TimeUnit.MILLISECONDS.sleep(3);
if (!linkedBlockingDeque2.isEmpty()) {
// 自己的队列不为空, 就从自己的队列中取数据消费, 从头开始消费数据
System.out.println(Thread.currentThread().getName() + "从自己队列 Deque2中 的头部消费了一个产品:" + linkedBlockingDeque2.takeFirst());
} else if (!linkedBlockingDeque1.isEmpty()) {
// 如果 另一个队列不为空, 就从他的尾开始消费数据
System.out.println(Thread.currentThread().getName() + "从别人队列 Deque1中 的尾部消费了一个产品:" + linkedBlockingDeque1.takeLast());
} else {
flag2 = false;//这里结束消费
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("------------------------------------------");
}
}
// 停止生产的方法
public void stop() {
this.flag1 = false;
}
public static void main(String[] args) throws InterruptedException {
//工作窃取代码演示: 什么是工作窃取? 在生产者和消费者模型中,
// 每个消费者都对应一个阻塞队列(LinkedBlockingDeque),当消费者当前的队列中的任务消费完了后, 不会就此结束,
// 他会从另一个队列中获取对应的任务来进行消费,
// 这就是 LinkedBlockingDeque的好处,因为他是双端队列,可以从头和尾 来获取元素
/**
*
* 看到的效果就是: 消费者线程1, 从自己的队列Deque1 中, 从头部开始消费1-10, 之后,开始从 别人的队列Deque2中消费产品了
*
* 这里让生产者 1毫秒之后停止生产,然后消费者开始消费
*/
LinkedBlockingDeque<String> linkedBlockingDeque1 = new LinkedBlockingDeque<>();
LinkedBlockingDeque<String> linkedBlockingDeque2 = new LinkedBlockingDeque<>();
LinkedBlockingDequeDemo linkedBlockingDequeDemo = new LinkedBlockingDequeDemo(linkedBlockingDeque1, linkedBlockingDeque2);
new Thread(() -> {
try {
linkedBlockingDequeDemo.producer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "生产者线程").start();
new Thread(() -> {
try {
linkedBlockingDequeDemo.consumer1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "消费者线程1").start();
new Thread(() -> {
try {
linkedBlockingDequeDemo.consumer2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "消费者线程2").start();
TimeUnit.MILLISECONDS.sleep(1);
linkedBlockingDequeDemo.stop();
}
}
运行结果 : 可以看到 线程1,在自己的阻塞队列中消费完之后, 并没有结束,从别人的队列中来 获取任务来执行




JUC 并发编程--10, 阻塞队列之--LinkedBlockingDeque 工作窃取, 代码演示的更多相关文章
- JUC 并发编程--07 阻塞队列版本的 生产者消费者(不使用synchronized和 lock),也有一些疑惑,最终解惑
直接上代码: 前提是你已经 熟悉了原子类,volatile,和阻塞队列 public class JucPCdemo03 { /** * 阻塞队列的应用: 这里实现的生产者消费者,生产一个消费一个 * ...
- JUC 并发编程--09, 阻塞队列: DelayQueue, PriorityBlockingQueue ,SynchronousQueue, 定时任务线程池: ScheduledThreadPoolExecutor
先看DelayQueue 这个是用优先级队列实现的无界限的延迟队列,直接上代码: /** * 这个是 {@link DelayQueue} 延时队列 的验证使用类 */ class MyDelayed ...
- JUC 并发编程--06, 阻塞队列(7种), 阻塞等待 api的 代码验证
这些队列的 api ,就是添加队列,出队列,检测对首元素, 由于 add()--remove(), offer()--poll(),太简单这里不做验证, 只验证后二组api: 阻塞等待( put()- ...
- Java并发编程:阻塞队列(转载)
Java并发编程:阻塞队列 在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList), ...
- 【转】Java并发编程:阻塞队列
在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList),这些工具都为我们编写多线程程 ...
- 12、Java并发编程:阻塞队列
Java并发编程:阻塞队列 在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList), ...
- (转)Java并发编程:阻塞队列
Java并发编程:阻塞队列 在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList), ...
- java并发编程学习: 阻塞队列 使用 及 实现原理
队列(Queue)与栈(Stack)是数据结构中的二种常用结构,队列的特点是先进先出(First In First Out),而Stack是先进后出(First In Last Out),说得通俗点: ...
- java并发编程:阻塞队列
一.几种主要的阻塞队列 自从Java 1.5之后,在java.util.concurrent包下提供了若干个阻塞队列,主要有以下几个: ArrayBlockingQueue:基于数组实现的一个阻塞队列 ...
随机推荐
- Linux配置yum源(本地源和网络源)
目录 一:配置本地yum源 二:配置网络yum源 更新源可以获取最新的软件信息,以更新您的系统 Redhat7配置源 YUM(Yellow dog Updater Modified): yum是Re ...
- POJ1149 PIGS(最大流)
题意: 有一个人,他有m个猪圈,每个猪圈里面有一定数量的猪,但是每个猪圈的门都是锁着的,他自己没有钥匙,只有顾客有钥匙,一天依次来了n个顾客,(记住是依次来的)他们每个人都有一些钥匙,和他 ...
- 第六部分 数据搜索之使用HBASE的API实现条件查询
题目 使用HADOOP的MAPReduce,实现以下功能: (1)基于大数据计算技术的条件查询:使用mapreduce框架,实现类似Hbase六个字段查询的功能 (2)时段流量统计:以hh:mm:ss ...
- spring和mybatis整合时Access denied for user '***'@'localhost' (using password: YES)错误的解决方案
参考文章:博客园文章 参考解决办法: 将数据库配置文件格式 key=value 改为 jdbc.key=value 以下为问题分析 使用Spring + Mybatis + Mysql整合时,测试报错 ...
- sharding JDBC 不支持批量导入解决方法
package com.ydmes.service.impl.log; import com.ydmes.domain.entity.log.BarTraceBackLog;import org.sp ...
- phpstorm 实现分屏显示
- Linux上的Shebang符号(#!)
使用Linux或者unix系统的同学可能都对#!这个符号并不陌生,但是你真的了解它吗? 本文了将给你简单介绍一下Shebang("#!")这个符号. 首先,这个符号(#!)的名称, ...
- CSS filter 有哪些神奇用途
背景 基本概念 CSS filter 属性将模糊或颜色偏移等图形效果应用于元素形成滤镜,滤镜通常用于调整图像,背景和边框的渲染.它的值可以为 filter 函数 <filter-function ...
- kubernetes客户端client-go使用
下载地址: https://github.com/kubernetes/client-go 官方使用文档参考:https://v1-16.docs.kubernetes.io/docs/referen ...
- [bug] jupyter notebook:服务在阿里云上启动,本地浏览器无法访问
问题 在阿里云上装了个jupyter,服务正常启动了,但网页上无法访问 排查 安全组已经设置过了,7777端口 在宝塔面板查看,发现7777端口并没有开,打开就可以访问了 原来阿里云的安全组和防火墙是 ...