目录
java中DelayQueue的使用
简介
今天给人人先容一下DelayQueue,DelayQueue是BlockingQueue的一种,以是它是线程平安的,DelayQueue的特点就是插入Queue中的数据可以根据自界说的delay时间举行排序。只有delay时间小于0的元素才能够被取出。
DelayQueue
先看一下DelayQueue的界说:
public class DelayQueue extends AbstractQueue
implements BlockingQueue
从界说可以看到,DelayQueue中存入的工具都必须是Delayed的子类。
Delayed继续自Comparable,而且需要实现一个getDelay的方式。
为什么这样设计呢?
由于DelayQueue的底层存储是一个PriorityQueue,在之前的文章中我们讲过了,PriorityQueue是一个可排序的Queue,其中的元素必须实现Comparable方式。而getDelay方式则用来判断排序后的元素是否可以从Queue中取出。
DelayQueue的应用
DelayQueue一样平常用于生产者消费者模式,我们下面举一个详细的例子。
首先要使用DelayQueue,必须自界说一个Delayed工具:
@Data
public class DelayedUser implements Delayed {
private String name;
private long avaibleTime;
public DelayedUser(String name, long delayTime){
this.name=name;
//avaibleTime = 当前时间+ delayTime
this.avaibleTime=delayTime + System.currentTimeMillis();
}
@Override
public long getDelay(TimeUnit unit) {
//判断avaibleTime是否大于当前系统时间,并将效果转换成MILLISECONDS
long diffTime= avaibleTime- System.currentTimeMillis();
return unit.convert(diffTime,TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed o) {
//compareTo用在DelayedUser的排序
return (int)(this.avaibleTime - ((DelayedUser) o).getAvaibleTime());
}
}
上面的工具中,我们需要实现getDelay和compareTo方式。
接下来我们建立一个生产者:
@Slf4j
@Data
@AllArgsConstructor
class DelayedQueueProducer implements Runnable {
private DelayQueue delayQueue;
private Integer messageCount;
private long delayedTime;
@Override
public void run() {
for (int i = 0; i < messageCount; i++) {
try {
DelayedUser delayedUser = new DelayedUser(
new Random().nextInt(1000)+"", delayedTime);
log.info("put delayedUser {}",delayedUser);
delayQueue.put(delayedUser);
Thread.sleep(500);
} catch (InterruptedException e) {
log.error(e.getMessage(),e);
}
}
}
}
在生产者中,我们每隔0.5秒建立一个新的DelayedUser工具,并入Queue。
再建立一个消费者:
@Slf4j
@Data
@AllArgsConstructor
public class DelayedQueueConsumer implements Runnable {
private DelayQueue delayQueue;
private int messageCount;
@Override
public void run() {
for (int i = 0; i < messageCount; i++) {
try {
DelayedUser element = delayQueue.take();
log.info("take {}",element );
} catch (InterruptedException e) {
log.error(e.getMessage(),e);
}
}
}
}
在消费者中,我们循环从queue中获取工具。
最后看一个挪用的例子:
@Test
public void useDelayedQueue() throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(2);
DelayQueue queue = new DelayQueue<>();
int messageCount = 2;
long delayTime = 500;
DelayedQueueConsumer consumer = new DelayedQueueConsumer(
queue, messageCount);
DelayedQueueProducer producer = new DelayedQueueProducer(
queue, messageCount, delayTime);
// when
executor.submit(producer);
executor.submit(consumer);
// then
executor.awaitTermination(5, TimeUnit.SECONDS);
executor.shutdown();
}
上面的测试例子中,我们界说了两个线程的线程池,生产者发生两条新闻,delayTime设置为0.5秒,也就是说0.5秒之后,插入的工具能够被获取到。
线程池在5秒之后会被关闭。
运行看下效果:
[pool-1-thread-1] INFO com.flydean.DelayedQueueProducer - put delayedUser DelayedUser(name=917, avaibleTime=1587623188389)
[pool-1-thread-2] INFO com.flydean.DelayedQueueConsumer - take DelayedUser(name=917, avaibleTime=1587623188389)
[pool-1-thread-1] INFO com.flydean.DelayedQueueProducer - put delayedUser DelayedUser(name=487, avaibleTime=1587623188899)
[pool-1-thread-2] INFO com.flydean.DelayedQueueConsumer - take DelayedUser(name=487, avaibleTime=1587623188899)
我们看到新闻的put和take是交替举行的,相符我们的预期。
若是我们做下修改,将delayTime修改为50000,那么在线程池关闭之前插入的元素是不会过时的,也就是说消费者是无法获取到效果的。
总结
DelayQueue是一种有新鲜特征的BlockingQueue,可以在需要的时刻使用。
迎接关注我的民众号:程序那些事,更多精彩等着您!
更多内容请接见 www.flydean.com
原文链接:https://www.cnblogs.com/flydean/p/java-delayqueue.html
本站声明:网站内容来源于网络,若有侵权,请联系我们,我们将及时处理。