JUC 并发编程--09, 阻塞队列: DelayQueue, PriorityBlockingQueue ,SynchronousQueue, 定时任务线程池: ScheduledThreadPoolExecutor
先看DelayQueue 这个是用优先级队列实现的无界限的延迟队列,直接上代码:
/**
* 这个是 {@link DelayQueue} 延时队列 的验证使用类
*/
class MyDelayed implements Delayed {
private long delayTime;//该任务在队列中的延迟时间
private long expire;//这个时间: 表示过时时间+当前时间, 到期时间
private String taskName;//任务名字
@Override
public String toString() {
return "MyDelayed{" +
"delayTime=" + delayTime +
", expire=" + expire +
", taskName='" + taskName + '\'' +
'}';
}
public MyDelayed(long delayTime, String taskName) {
this.delayTime = delayTime;
this.taskName = taskName;
this.expire = System.currentTimeMillis() + delayTime;
}
@Override
public long getDelay(TimeUnit unit) {
// 这个方法是 定义了 剩余到期时间
//unit.convert(), 这个方法是转换, 将数值转换为毫秒, 将延时时间转换为毫秒
return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed o) {
// 这里设置比较规则,从小到大
return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
// 从大到小
//return (int) ( o.getDelay(TimeUnit.MILLISECONDS) - this.getDelay(TimeUnit.MILLISECONDS));
}
public static void main(String[] args) throws InterruptedException {
boolean flag = true;
/**
* 延迟队列: 这是一个无界队列,添加元素时候不阻塞, 每个任务里面都有一个延迟时间,
* 超过这个时间,才将任务取出来,且这个队列中放的元素,只能是 MyDelayed,(实现了Delayed)
*/
DelayQueue<MyDelayed> delayQueue = new DelayQueue<>();
Random random = new Random();
for (int i = 0; i < 20; i++) {
MyDelayed myDelayed = new MyDelayed(random.nextInt(500), "任务" + i);
delayQueue.put(myDelayed);
}
while (flag) {
// 这里使用 take(). 阻塞获取的方法,当获取不到的时候,会阻塞,直到延时时间到期,获取到为止
//还有一个 获取方法: poll(). 点进源码看到: 延时时间没到,获取结果为null, 当延时时间到了之后,才会获取到结果
MyDelayed take = delayQueue.take();
System.out.println(take);
if (delayQueue.size() == 0) {
flag = false;
}
}
}
}
运行结果: 
PriorityBlockingQueue, 这个队列,是支持优先级排序的 无界队列, 代码演示:
public class PriorityBlockingQueueDemo {
/**
* PriorityBlockingQueue; 无界队列, 添加元素的时候不阻塞
* <p>
* 这个队列是基于优先级的阻塞队列, 且只会阻塞消费者,不会阻塞生成者,所以在使用的时候,不能让生成的速度大于消费的速度,否则时间一长,会造成堆空间溢出({@link OutOfMemoryError})
*/
public static void main(String[] args) throws InterruptedException {
boolean flag = true;
// PriorityBlockingQueue 队列中的元素 如果是基本数据类型,默认排序时从小到大, 如果是对象,可以实现Comparable接口来指定排序规则
//PriorityBlockingQueue<String> priorityBlockingQueue = new PriorityBlockingQueue();
PriorityBlockingQueue<MyTask> priorityBlockingQueue = new PriorityBlockingQueue();
Random random = new Random();
for (int i = 0; i < 20; i++) {
//priorityBlockingQueue.put("任务"+i);
priorityBlockingQueue.put(new MyTask("任务" + i, random.nextInt(100)));
}
while (flag) {
//String take = priorityBlockingQueue.take();
MyTask take = priorityBlockingQueue.take();
System.out.println(take);
if (priorityBlockingQueue.size() == 0) {
flag = false;
}
}
}
}
class MyTask implements Comparable<MyTask> {
private String taskName;
private int age;
public MyTask(String taskName, int age) {
this.taskName = taskName;
this.age = age;
}
@Override
public String toString() {
return "MyTask{" +
"taskName='" + taskName + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(MyTask o) {
return o.age - this.age;
}
}
运行结果为: 可以看到是按照顺序来取出来的

SynchronousQueue, 这个队列是 不存储元素的队列,(传球手), 用这个队列来实现一个 生产者,消费者, 生产一个,消费一个, 代码如下:
class SynchronousQueueDemo {
private static volatile boolean flag = true;
private static AtomicInteger atomicInteger = new AtomicInteger();
private BlockingQueue blockingQueue;
public SynchronousQueueDemo(BlockingQueue blockingQueue) {
this.blockingQueue = blockingQueue;
System.out.println(blockingQueue.getClass().getName());
}
// 生产者
public void producer() throws InterruptedException {
String data = "";
while(flag){
data = atomicInteger.getAndIncrement()+"";//这是产品
TimeUnit.SECONDS.sleep(1);// 1秒生成一个产品
boolean offer = blockingQueue.offer(data);
if(offer){
System.out.println(Thread.currentThread().getName() + "添加成功, 元素为:" + data+"--队列是否为空:"+blockingQueue.isEmpty());
}else{
System.out.println(Thread.currentThread().getName() + "添加失败");
}
}
}
// 消费者
public void consumer() throws InterruptedException {
while(flag){
try {
System.out.println("消费了一个产品:"+blockingQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("------------------------------------------");
}
}
// 停止方法
public void stop(){
this.flag = false;
}
public static void main(String[] args) throws InterruptedException {
/**
* 相当于一个传球手, 不存储元素的队列, 所以容量都为空
*
* SynchronousQueue 它是一个对于元素来说空了才能存入,存在才能取出的队列,只保留一个元素在queue里。
* 但是用处在哪里?如果替换成其它queue,比如ArrayBlockingQueue,会使得哪些事情做不到?
*
* 首先,它也是blockingqueue的一个实现,内部采用的就是ArrayBlockingQueue的阻塞原语,所以在功能上完全可以用ArrayBlockingQueue替换之,
* 但是SynchronousQueue 是轻量级的,SynchronousQueue 不具有任何内部容量,甚至不具有一的容量,我们可以用来在线程间安全的交换单一元素。
* 所以功能比较单一,优势应该就在于轻量吧~
*/
SynchronousQueueDemo synchronousQueue = new SynchronousQueueDemo(new SynchronousQueue());
SynchronousQueueDemo linkedTransferQueue = new SynchronousQueueDemo(new LinkedTransferQueue<String>());
new Thread(()->{
try {
linkedTransferQueue.producer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(()->{
try {
linkedTransferQueue.consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
TimeUnit.SECONDS.sleep(5);
synchronousQueue.stop();
}
}
运行结果:
关于定时任务线程池的分析
public static void main(String[] args) {
/**
* corePoolSize:4
* maximumPoolSize: Integer.MAX_VALUE
* keepAliveTime: 0
* 单位: 微秒
* 阻塞队列: DelayedWorkQueue
* 线程工厂: Executors.defaultThreadFactory()
* 拒绝策略: AbortPolicy,
*
*/
ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(4);
/**
* 这里引用别人博客:[https://www.cnblogs.com/txmfz/p/10338334.html]()
* 定时任务线程池, 内部使用的队列是: DelayedWorkQueue, 用来定时从队列中取任务
*
* 这里不是直接使用的 DelayQueue(队列放的元素 只能是 Delayed类) ,是因为点进 DelayedWorkQueue源码可以看到内部维护了一个数组:RunnableScheduledFuture[]
* 而 RunnableScheduledFuture 这个类最终是继承了 Delayed 类,
* 他是DelayQueue的扩展, 是: 优先级队列实现+延迟队列实现 说明 DelayedWorkQueue的功能比 DelayQueue更强大,
*/
}
JUC 并发编程--09, 阻塞队列: DelayQueue, PriorityBlockingQueue ,SynchronousQueue, 定时任务线程池: ScheduledThreadPoolExecutor的更多相关文章
- JUC 并发编程--07 阻塞队列版本的 生产者消费者(不使用synchronized和 lock),也有一些疑惑,最终解惑
直接上代码: 前提是你已经 熟悉了原子类,volatile,和阻塞队列 public class JucPCdemo03 { /** * 阻塞队列的应用: 这里实现的生产者消费者,生产一个消费一个 * ...
- JUC 并发编程--10, 阻塞队列之--LinkedBlockingDeque 工作窃取, 代码演示
直接上代码 class LinkedBlockingDequeDemo { // 循环是否结束的开关 private static volatile boolean flag1 = true; pri ...
- Python并发编程之消息队列补充及如何创建线程池(六)
大家好,并发编程 进入第六篇. 在第四章,讲消息通信时,我们学到了Queue消息队列的一些基本使用.昨天我在准备如何创建线程池这一章节的时候,发现对Queue消息队列的讲解有一些遗漏的知识点,而这些知 ...
- 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),说得通俗点: ...
随机推荐
- android apk壳
壳对于有过pc端加解密经验的同学来说并不陌生,android世界中的壳也是相同的存在.看下图(exe = dex): 概念清楚罗,我们就说下:壳最本质的功能就是实现加载器.你看加壳后,系统是先执 ...
- 1.关于逆向工程(RE、RCE)-笔记
名词 逆向工程(Reverse Engineering,简称RE):代码逆向工程(Reverse Code Engineering,简称RCE). 逆向分析方法 静态分析:不执行代码,观察外部特征.获 ...
- 【python】Leetcode每日一题-删除排序链表中的重复元素
[python]Leetcode每日一题-删除排序链表中的重复元素 [题目描述] 存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除所有重复的元素,使每个元素 只出现一次 . 返回同 ...
- 一文带你详细介绍c++中的std::move函数
前言 在探讨c++11中的Move函数前,先介绍两个概念(左值和右值) 左值和右值 首先区分左值和右值 左值是表达式结束后依然存在的持久对象(代表一个在内存中占有确定位置的对象) 右值是表达式结束时不 ...
- 推荐一个不得不知道的 Visual Studio 快捷键
不得不说,Visual Studio 内置了很多非常棒的快捷键,借助于这些快捷键我们甚至不需要再使用鼠标,就可以快速高效的编写代码,因此学习和熟悉这些快捷键是值得的. 其中有一个快捷键是我非常喜欢,也 ...
- Codeforces Round #691 (Div. 2)
A. Red-Blue Shuffle 题意:有两个长度为n的数组,数组a和数组b,问那个数组中的数字相比之下比另一个数组中相应位置的元素值更大一些,如果数组a大就输出RED,如果数组b大就输出BLU ...
- CRM系统实现自动化的“三部曲”
在了解CRM系统的自动化的时候,我们先来看一下CRM能干什么. 从上面的流程图我们就可以看出,CRM可以管理售前,售中和售后的整个客户生命周期. 为什么在复杂的客户生命周期中需要自动化呢? 当然是为了 ...
- cmake和make
学计算机的,在写代码的时候,IDE安装好,环境按着教程配置好,就直接代码了,编辑器的具体原理只是一知半解,现在来系统学习一下,为了方便以后学习HElib! make和cmake 写程序大体步骤为: 1 ...
- Powershell阻止确认
要阻止弹出确认提示,需要设置-Confirm为false, new-VM -Name $hostname -Template $template -VMHost 10.11.31.5 -OSCusto ...
- [bug] Maven项目缺少Maven Dependencies
参考 https://blog.csdn.net/whitemiao/article/details/90177135