先看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的更多相关文章

  1. JUC 并发编程--07 阻塞队列版本的 生产者消费者(不使用synchronized和 lock),也有一些疑惑,最终解惑

    直接上代码: 前提是你已经 熟悉了原子类,volatile,和阻塞队列 public class JucPCdemo03 { /** * 阻塞队列的应用: 这里实现的生产者消费者,生产一个消费一个 * ...

  2. JUC 并发编程--10, 阻塞队列之--LinkedBlockingDeque 工作窃取, 代码演示

    直接上代码 class LinkedBlockingDequeDemo { // 循环是否结束的开关 private static volatile boolean flag1 = true; pri ...

  3. Python并发编程之消息队列补充及如何创建线程池(六)

    大家好,并发编程 进入第六篇. 在第四章,讲消息通信时,我们学到了Queue消息队列的一些基本使用.昨天我在准备如何创建线程池这一章节的时候,发现对Queue消息队列的讲解有一些遗漏的知识点,而这些知 ...

  4. JUC 并发编程--06, 阻塞队列(7种), 阻塞等待 api的 代码验证

    这些队列的 api ,就是添加队列,出队列,检测对首元素, 由于 add()--remove(), offer()--poll(),太简单这里不做验证, 只验证后二组api: 阻塞等待( put()- ...

  5. Java并发编程:阻塞队列(转载)

    Java并发编程:阻塞队列 在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList), ...

  6. 【转】Java并发编程:阻塞队列

    在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList),这些工具都为我们编写多线程程 ...

  7. 12、Java并发编程:阻塞队列

    Java并发编程:阻塞队列 在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList), ...

  8. (转)Java并发编程:阻塞队列

    Java并发编程:阻塞队列 在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList), ...

  9. java并发编程学习: 阻塞队列 使用 及 实现原理

    队列(Queue)与栈(Stack)是数据结构中的二种常用结构,队列的特点是先进先出(First In First Out),而Stack是先进后出(First In Last Out),说得通俗点: ...

随机推荐

  1. Linux文件共享服务之NFS

    NFS(Network File System) 网络文件系统,是FreeBSD支持的文件系统中的一种,它允许网络中的计算机之间通过TCP/IP网络共享资源.在NFS的应用中,本地NFS的客户端应用可 ...

  2. Python中的Pexpect模块的简单使用

    Pexpect 是一个用来启动子程序并对其进行自动控制的 Python 模块. Pexpect 可以用来和像 ssh.ftp.passwd.telnet 等命令行程序进行自动交互.以下所有代码都是在K ...

  3. Python脚本破解图形验证码(tesserocr和pytesseract)

    在学习之前,我们先了解OCR.tesseract.tesserocr.pytesseract和opencv这几个跟图片处理有关的库. OCR(Optical Character Recognition ...

  4. xml数据解析和生成

    java中xml的解析方式有许多,有java自带的DOM.SAX,android中的PULL,其它的还有DOM4J.JDOM等. 本文简要讲述DOM.SAX.PULL三种方式. 1.DOM方法 缺点: ...

  5. layui图片上传

    <!DOCTYPE html><html><head> <meta charset="utf-8"> <title>up ...

  6. 百度地图api根据用户IP获取用户位置(PHP)

    1.百度地图开放平台找的你的ak ,链接:http://lbsyun.baidu.com/apiconsole/key 2.获取用户ip地址(外网ip 服务器上可以获取用户外网Ip 本机ip地址只能获 ...

  7. java使用户EasyExcel导入导出excel

    使用alibab的EasyExce完成导入导出excel 一.准备工作 1.导包 <!-- poi 相关--> <dependency> <groupId>org. ...

  8. 从 demo 到生产 - 手把手写出实战需求的 Flink 广播程序

    Flink 广播变量在实时处理程序中扮演着很重要的角色,适当的使用广播变量会大大提升程序处理效率. 本文从简单的 demo 场景出发,引入生产中实际的需求并提出思路与部分示例代码,应对一般需求应该没有 ...

  9. 【BUAA 软工博客作业】个人博客作业

    项目 内容 课程:2020春季软件工程课程博客作业(罗杰,任健) 博客园班级链接 作业:热身作业,阅读并撰写博客 作业要求 课程目标 学习大规模软件开发的技巧与方法,锻炼开发能力 作业目标 阅读教材, ...

  10. 企业CRM系统选型的标准有哪些?

    随着市场的发展,企业开始意识到客户的重要性.越来越多的企业形成了"以客户为核心"的理念,更加注重客户数据和管理,因此CRM客户关系管理系统成为企业的首选.选择一个适合企业的CRM系 ...