4.使用带有延迟元素的线程安全列表
本范例使用DelayQueue类;这个类可以存放带有激活日期的元素。当调用方法从队列中返回或者提取元素时,未来的日期将被忽略。这些元素对于这些方法是不可见的。
为了具有调用行为,存放到DelayQueue类中的元素必须继承Delayed接口。Delayed接口使对象成为延迟对象,它使存放在DelayQueue类中的对象具有激活日期,即到了
激活日期的时间。该接口强制执行下面的方法:
1.compareTo(Delayed o):Delayed接口继承了Comparable接口,因此有这个方法,如果当前对象的延迟至小于参数对象的值,将返回一个小于0的值。
如果当前对象的延迟值小于参数对象的值,将返回一个小于0的值,如果当前对象的延迟值大于参数对象的值,将返回一个大于0的值,如果两者的延迟值相等则返回0.
2.getDelay(TimeUnit unit):这个方法返回到激活日期的剩余时间,单位由单位参数指定。该方法用来计算激活日期和实际日期之间的纳秒书。
者两个日期都是Date对象,并使用日期对象的getTime()方法将日期转换为毫秒数进行比较,然后通过getDelay()方法的传入参数
TimeUnit的convert()方法将时间间隔转换为event激活时间的剩余纳秒数。DelayQueue类本身是使用纳秒工作的,对于使用者来说是透明的。
使用方法:
clear():移除队列中的所有元素
offer(E e):E是DelayQueue的泛型参数,表示传入参数的类型,这个方法把参数对应的元素插入到队列中。
peek():返回队列中的第一个元素,但是不将其移除。
take():返回队列中的第一个元素,并将其移除。如果队列为空,线程将被阻塞直到队列中有可用的元素。
/**
*
* @author fcs
* @date 2015-6-21
* 描述:使用带有延迟元素的线程安全列表
* 说明:
*/
public class Event implements Delayed{
private Date startDate;
public Event(Date startDate) {
this.startDate = startDate;
}
/**
* 该方法接收一个Delayed对象为参数,并比较两者延迟值的大小
*/
@Override
public int compareTo(Delayed o) {
long result = this.getDelay(TimeUnit.NANOSECONDS) - o.getDelay(TimeUnit.NANOSECONDS);
if(result < 0){
return -1;
}else if(result > 0 ){
return 1;
}
return 0;
}
@Override
public long getDelay(TimeUnit unit) {
Date now = new Date();
long diff = startDate.getTime() - now.getTime();
return unit.convert(diff, TimeUnit.MILLISECONDS);
}
}
public class Task implements Runnable{
private int id;
private DelayQueue<Event> queue;
public Task(int id, DelayQueue<Event> queue) {
this.id = id;
this.queue = queue;
}
@Override
public void run() {
Date now = new Date();
Date delay = new Date();
//设置延迟时间
delay.setTime(now.getTime()+(id*10000));
for(int i =0;i< 100;i++){
Event event = new Event(delay);
System.out.println("you have added a event to queue");
queue.add(event);
}
}
}
public class Main {
public static void main(String[] args) {
DelayQueue<Event> queue = new DelayQueue<Event>();
Thread threads []= new Thread[5];
for(int i =0; i < threads.length;i++ ){
Task task = new Task(i+1,queue);
threads[i] = new Thread(task);
}
for(int i =0;i< threads.length;i++){
threads[i].start();
}
for(int i =0 ; i<threads.length;i++){
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
do{
int counter = 0;
Event event;
do{
event = queue.poll();
if(event != null)counter ++;
}while(event != null);
System.out.printf("At %s you have read %d events \n",new Date(),counter);
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}while(queue.size() > 0); //该方法返回列表元素中的总个数,包括活动和非活动的元素
}
}