1.什么是延时队列
delayed元素的无限制阻塞队列,在该队列中,仅当元素的延迟到期时才可以使用该元素。
队列的开头是该Delayed元素,其延迟在过去最远的时间到期。 如果没有延迟,则没有头, poll将返回null 。
当元素getDelay(TimeUnit.NANOSECONDS)方法返回小于或等于零的值时,就会发生过期。
即使未到期的元素无法使用take或poll删除,它们也被视为普通元素。 例如, size方法返回过期和未过期元素的计数。
此队列不允许使用null元素。 此类及其迭代器实现Collection和Iterator接口的所有可选方法。
不保证方法iterator()提供的Iterator以任何特定顺序遍历DelayQueue的元素。(官方注释翻译)
2.使用场景
定时任务,需要定时触发的就可以使用延时队列,把需要触发的任务放到延时队列中。
1.订单超时,下单超过15分钟不付款自动取消订单。
2.清除内存中缓存的对象,如果超过时间就清除。
3. 关闭空闲连接。服务器中,有很多客户端的连接,空闲一段时间之后需要关闭之。
4. 任务超时处理。在网络协议滑动窗口请求应答式交互时,处理超时未响应的请求等。
3.上代码
创建一个Task类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Task implements Delayed {
private int taskId;
private String taskName;
private long scheduleAt;
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(this.scheduleAt - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed o) {
Task task = (Task) o;
return Long.compare(this.scheduleAt, task.scheduleAt);
}
}
简单的调度系统
public class Schedule extends Thread {
public static final DelayQueue<Task> DELAY_QUEUE = new DelayQueue<>();
@Override
public void run() {
while (true) {
try {
Task task = DELAY_QUEUE.take();
System.out.println("Current time" + System.currentTimeMillis() + " trigger task: " + task);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
//用于创建任务
new Thread(() -> {
for (int i = 0; i < 10; i++) {
Task task = new Task(i, "task" + i, System.currentTimeMillis());
System.out.println("Create task: " + task);
DELAY_QUEUE.offer(task);
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
//定时任务的线程
Schedule schedule = new Schedule();
schedule.start();
//阻塞
System.out.println(System.in);
}
}