先看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更强大,
*/
}

最新文章

  1. 剑指Offer面试题:12.在O(1)时间删除链表结点
  2. CSS之详解:active选择器
  3. Mac Pro 编译安装 PHP扩展 -- Swoole扩展
  4. 【转】JVM内存模型
  5. 一个CFile::Remove引起的奇怪问题
  6. Keepalived+MySQL双主
  7. Linux相关命令
  8. Qt制作应用插件
  9. 在Gridview编辑时添加DropDownList控件并设置默认值
  10. php 读取二进制文件
  11. 关于easyui隐藏后数据不能刷新??
  12. 让linux远程主机在后台运行脚本
  13. jq 滚轮监听事件
  14. Cocos2D旋转炮塔到指定角度(三)
  15. HBase源码实战:BufferedMutator
  16. 我发起了一个 用 javascript 写一个 Office 的 开源项目 JS Office
  17. python,类和对象(二),self 、__init__(self,param[,param...])、__private(私有变量)
  18. 安卓开发 1配置环境 (JDK+Andriod stiuio)
  19. [转]delphi 有授权许可的字符串拷贝函数源码
  20. android--简单的电话拨号功能

热门文章

  1. 查找和定位Android应用的按钮点击事件的代码位置基于Xposed Hook实现
  2. PyCharm调试程序
  3. CVE-2018-8174(双杀漏洞)复现
  4. phpstorm 实现分屏显示
  5. 网络请求axios
  6. 语音降噪论文“A Hybrid Approach for Speech Enhancement Using MoG Model and Neural Network Phoneme Classifier”的研读
  7. .NET之API版本控制
  8. 【敏杰开发】Scrum Meeting 博客汇总
  9. [Java] 数据分析--统计
  10. [bug] CM / CDH 主机运行状态不良情况