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),说得通俗点: ...
随机推荐
- UVA11729突击战(汇报和执行任务)
题意: 你是一个长官,有一些士兵要跟你先汇报任务后在去执行任务,每次只能接受一个人的汇报,但是每一时刻可以有多个士兵在执行任务,问所有任务执行完要的最小时间. 思路: 按执行 ...
- python中让输出不换行
Python2.x python2.x中输出默认是换行的,为了抑制换行,可以在打印最后加一个逗号 Python3.x 到了python3中,print 变成一个函数,这种语法便行不通了. 我们可以使用 ...
- PhpMyWind储存型XSS漏洞练习(CVE-2017-12984)
0x01 介绍 又是一款开源CMS内容管理系统PhpMyWind,在小于等于5.4版本中存在储存型XSS漏洞.如下图所示,这个就是发生储存型XSS漏洞的代码 0x02 演示 1.第一张图是客户留言时, ...
- 攻防世界Web刷题记录(新手区)
攻防世界Web刷题记录(新手区) 1.ViewSource 题如其名 Fn + F12 2.get post 3.robots robots.txt是搜索引擎中访问网站的时候要查看的第一个文件.当一个 ...
- python三元(三目)运算
传统的if,else写法 三元运算 name="alex" if 1==1 else "SB"
- IT培训软件测试怎么样,问问“过来人”!
经常看到有人在网上发帖子问:"XX培训(IT培训机构)怎么样,学过的老哥可以出来讲讲真话吗?"问这种问题的同学,来,站起来!我不得不在这儿说你两句:你要想知道一家IT培训机构到底怎 ...
- [源码解析] 并行分布式任务队列 Celery 之 负载均衡
[源码解析] 并行分布式任务队列 Celery 之 负载均衡 目录 [源码解析] 并行分布式任务队列 Celery 之 负载均衡 0x00 摘要 0x01 负载均衡 1.1 哪几个 queue 1.1 ...
- 高性能MySQL-索引
创建索引-高效索引 1.1 索引初体验 1.1.1 介绍 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针. 索引的作用是做数据的快速检 ...
- Codeforces Beta Round #73(Div2)
A - Chord 题意:就是环中有12个字符,给你三个字符,判断他们之间的间隔,如果第一个和第二个间隔是3并且第二个和第三个间隔是4,那么就输出minor,如果第一个和第二个间隔是4并且第二个和第三 ...
- 【技术博客】基于vue的前端快速开发(工具篇)
一.Vue教程 vue.js是一套构建用户界面的渐进式框架.vue采用自底向上增量开发的设计.vue的核心库只关心视图层,非常容易学习,非常容易与其它库和已有项目整合.vue完全有能力驱动采用单文件组 ...