DelayQueue阻塞队列系列文章
DelayQueue阻塞队列第一章:代码示例
DelayQueue阻塞队列第二章:源码解析
介绍
在实际的业务中,DelayQueue有很广泛的使用场景,他是java并发包concurrent下的DelayQueue类,主要作用就是进行任务的延时执行
业务场景
- 订单定时过期
- 任务定时处理
- 等一切需要时间间隔执行的任务
缺点
因为是java类,所以当你的服务器重启的时候,你DelayQueue中也就不存在了,保存的任务也会随之消失,个人在这一块的处理方法是在重新启动服务器的时候,重新将需要进行延迟处理的任务加入到队列当中,所以一般需要进行延迟处理的任务我都会设置一个过期时间的字段,一方面在显示上很直观,主要目的其实就是为了在重新启动服务器的时候可以重新计算并将任务加入到队列中来
示例代码
代码是网上就可以找到的代码,一方面通过这个代码配合我的源码解析加深对DelayQueue的理解,具体的实际业务场景可以根据这个模版代码进行改编
DelayedElement类(构建封装实际传入数据的构建类)
该类的作用封装的加入队列任务,实现了接口Delayed,需重写方法getDelay方法和
class DelayedElement implements Delayed {
private final long delay; //延迟时间
private final long expire; //到期时间
private final String msg; //实际保存的数据
private final long now; //创建时间
public DelayedElement(long delay, String msg) {
this.delay = delay;
this.msg = msg;
expire = System.currentTimeMillis() + delay; //到期时间 = 当前时间+延迟时间
now = System.currentTimeMillis();
}
/**
* 获得延迟时间 用过期时间-当前时间
* @param unit
* @return
*/
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(this.expire-System.currentTimeMillis(),TimeUnit.MILLISECONDS);
}
/**
* 队列中内部比较排序
* @param o
* @return
*/
@Override
public int compareTo(Delayed o) {
return (int) (this.getDelay(TimeUnit.MILLISECONDS) -o.getDelay(TimeUnit.MILLISECONDS));
}
}
getDelay
该方法的作用是获取剩余到期时间,调用的地方参考DelayQueue源码解析,在该类中的take源码解析中,通过调用getDelay方法来判断是否需要从队列中取出元素
compareTo
该方法主要作用是根据指定的规则对队列中的数据进行排序
DelayQueueTest(延迟队列的业务实现类)
public class DelayQueueTest {
public static void main(String args[]){
DelayQueue<DelayedElement> delayQueue=new DelayQueue<DelayedElement>();
producer(delayQueue);//朝生产队列中添加任务事件
consumer(delayQueue);//从队列中获取任务并执行
while (true){
try {
TimeUnit.HOURS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private static void producer(DelayQueue<DelayedElement> delayQueue) {
new Thread(new Runnable() {
@Override
public void run() {
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
DelayedElement element = new DelayedElement(1000,"test");
delayQueue.offer(element);
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true){
try {
TimeUnit.MILLISECONDS.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("delayQueue size:"+delayQueue.size());
}
}
}).start();
}
/**
* 消费者,从延迟队列中获得数据,进行处理
* @param delayQueue
*/
private static void consumer(DelayQueue<DelayedElement> delayQueue) {
new Thread(new Runnable() {
@Override
public void run() {
while (true){
DelayedElement element = null;
try {
element = delayQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis()+"---"+element);
}
}
}).start();
}
}
该类使用了生产-消费者模式,所以代码的实现分为元素入队列和取出队列元素
入队操作就是将构建的DelayedElement加入到队列中去,然后在消费方法中取出元素
DelayQueue的使用方法较为简单,只是需要注意的是如果重启服务那么之前保存的任务将会消失,所以需要在项目启动的时候重新将任务加载进队列中来
- 技术理解不到或有错误之处欢迎指正
网友评论