注释来自java api
Delayed 元素的一个无界阻塞队列,只有在延迟期满时才能从中提取元素。该队列的头部 是延迟期满后保存时间最长的 Delayed 元素。如果延迟都还没有期满,则队列没有头部,并且 poll 将返回 null。当一个元素的 getDelay(TimeUnit.NANOSECONDS) 方法返回一个小于等于 0 的值时,将发生到期。即使无法使用 take 或 poll 移除未到期的元素,也不会将这些元素作为正常元素对待。例如,size 方法同时返回到期和未到期元素的计数。此队列不允许使用 null 元素。
public class DelayQueue<E extends Delayed>extends AbstractQueue<E>implements BlockingQueue<E>
获取并移除此队列的头部,在可从此队列获得到期延迟的元素之前一直等待(如有必要)。
将指定元素插入此延迟队列。
将指定元素插入此延迟队列。
获取并移除此队列的头,如果此队列不包含具有已到期延迟时间的元素,则返回 null。
获取但不移除此队列的头部;如果此队列为空,则返回 null。
返回此 collection 中的元素数。
自动移除此延迟队列的所有元素。
DelayQueue
因此我们必须先构造一个这样的子类, 假设有一个定时任务 Task, 在设定时间然后从队列取出执行他.
定时任务 Task
/**
*
* 定时任务
*/
public class Task {
// 任务id
private Integer id;
// 任务名称
private String name;
// 执行时间
private Long time;
public Task(Integer id, String name, Long time) {
this.id = id;
this.name = name;
this.time = time;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getTime() {
return time;
}
public void setTime(Long time) {
this.time = time;
}
@Override
public String toString() {
return "Task [id=" + id + ", name=" + name + ", time=" + new Date(time).toString() + "]";
}
}
Delayed 实现类:
因为我们并不想改变 Task 的结构, 所以另外创建一个实现类 TaskDelayed
public class TaskDelayed implements Delayed {
// 任务
private Task task;
public TaskDelayed(Task task) {
super();
this.task = task;
}
public Task getTask() {
return task;
}
@Override
public int compareTo(Delayed o) {
return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
}
@Override
public long getDelay(TimeUnit unit) {
long time = task.getTime();
long currentTime = System.currentTimeMillis();
return unit.convert(time - currentTime, TimeUnit.MILLISECONDS);
}
}
BlockingQueue<TaskDelayed> queue = new DelayQueue<>();
put 与 take (一直阻塞直到完成操作为止)
public static void main(String[] args) throws InterruptedException {
BlockingQueue<TaskDelayed> queue = new DelayQueue<>();
queue.put(new TaskDelayed(new Task(5, "ssss", System.currentTimeMillis() + 9000L)));
queue.put(new TaskDelayed(new Task(2, "ssss", System.currentTimeMillis() + 6000L)));
queue.put(new TaskDelayed(new Task(3, "ssss", System.currentTimeMillis() + 7000L)));
queue.put(new TaskDelayed(new Task(1, "ssss", System.currentTimeMillis() + 5000L)));
queue.put(new TaskDelayed(new Task(4, "ssss", System.currentTimeMillis() + 8000L)));
for(;;) {
System.out.println(queue.take().getTask() + "----" + new Date());
}
}
执行结果
Task [id=1, name=ssss, time=Wed Jan 23 14:09:12 CST 2019]----Wed Jan 23 14:09:12 CST 2019
Task [id=2, name=ssss, time=Wed Jan 23 14:09:13 CST 2019]----Wed Jan 23 14:09:13 CST 2019
Task [id=3, name=ssss, time=Wed Jan 23 14:09:14 CST 2019]----Wed Jan 23 14:09:14 CST 2019
Task [id=4, name=ssss, time=Wed Jan 23 14:09:15 CST 2019]----Wed Jan 23 14:09:15 CST 2019
Task [id=5, name=ssss, time=Wed Jan 23 14:09:16 CST 2019]----Wed Jan 23 14:09:16 CST 2019
这里取出的时间和系统当前时间一致, 因为我们指定了他取出的时间
关键方法在于 Delayed
public interface Delayed extends Comparable<Delayed> {
long getDelay(TimeUnit unit);
}
具体实现:
返回与此对象相关的剩余延迟时间,以给定的时间单位表示。
@Override
public long getDelay(TimeUnit unit) {
long time = task.getTime();
long currentTime = System.currentTimeMillis();
return unit.convert(time - currentTime, TimeUnit.MILLISECONDS);
}