java并发编程实战第六章(5)使用带有延迟元素的线程安全列表

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);   //该方法返回列表元素中的总个数,包括活动和非活动的元素
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值