DelayQueue实现延迟消息

最近想做一个定时推送消息的功能,经过调研了解到DelayQueue,消息对象需实现Delayed接口里的getDelay(TimeUnit unit)方法,由于Delayed继承了Comparable故需要实现compareTo方法,可用于决定消息的推送次序。以考试为例,设置每个考生的交卷时间点。

学生对象:

/**
 * 
 * @author     peiyu
 */
public class Student  implements Runnable,Delayed{    
    private String name;    //姓名
    private  Date date;   //交卷时间
    private String id; //编号
    public Student() {    

    }    
    public Student(String name, Date date, String id) {    
        super();    
        this.name = name;     
        this.date=date;    
        this.id=id;
    }    

    @Override    
    public void run() {    
        System.out.println(name + " 设置时间=" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date) + ";执行时间="+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));    
    }    

    @SuppressWarnings("static-access")
    @Override    
    public long getDelay(TimeUnit unit) {    
        return unit.convert(date.getTime() - System.currentTimeMillis(), unit.NANOSECONDS);    
    }    

    @Override    
    public int compareTo(Delayed o) {    
        Student that = (Student) o;    
        return date.getTime()> that.getDate().getTime()?1:(date.getTime() < that.getDate().getTime() ? -1 : 0);    
    }    
    public static class EndExam extends Student{    
        private ExecutorService exec;    
        public EndExam(Date date,String id, ExecutorService exec) {    
            super(null,date, id);    
            this.exec = exec;    
        }    
        @Override    
        public void run() {    
            exec.shutdownNow();    
        }    
    }
    @Override
    public boolean equals(Object obj) {
        Student student=(Student)obj;
        return this.id.equals(student.getId());
    }
    /**
     * 设置name.
     * @return 返回name
     */
    public String getName() {
        return name;
    }
    /**
     * 设置date.
     * @return 返回date
     */
    public Date getDate() {
        return date;
    }
    /**
     * 获取name.
     * @param name 要设置的name
     */
    public void setName(String name) {
        this.name = name;
    }
    /**
     * 获取date.
     * @param date 要设置的date
     */
    public void setDate(Date date) {
        this.date = date;
    }
    /**
     * 设置id.
     * @return 返回id
     */
    public String getId() {
        return id;
    }
    /**
     * 获取id.
     * @param id 要设置的id
     */
    public void setId(String id) {
        this.id = id;
    }
}    

教师类

public class Teacher  implements Runnable{    
    private DelayQueue<Student> students;    

    public Teacher(DelayQueue<Student> students,ExecutorService exec) {    
        super();    
        this.students = students;    
    }    

    @Override    
    public void run() {    
        try {    
            System.out.println("考试开始……");    
            while (!Thread.interrupted()) {    
                students.take().run();    
            }    
            System.out.println("考试结束……");    
        } catch (InterruptedException e) {    
            e.printStackTrace();    
        }    

    }    

}    

测试类,开始考试

public class Exam {
    public static void main(String[] args) throws ParseException {
        //创建延迟队列
        DelayQueue<Student> delayQueue = new DelayQueue<Student>();
        ExecutorService exec = Executors.newCachedThreadPool();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:SS");
        //将消息放入队列
        delayQueue.put(new Student("学生1", dateFormat.parse("2016-11-10 16:02:10"), "1"));
        delayQueue.put(new Student("学生2", dateFormat.parse("2016-11-10 16:09:10"), "2"));
        delayQueue.put(new Student("学生3", dateFormat.parse("2016-11-10 16:08:10"), "3"));
        delayQueue.put(new Student("学生4", dateFormat.parse("2016-11-10 16:06:10"), "4"));
        delayQueue.put(new Student("学生5", dateFormat.parse("2016-11-10 16:03:10"), "5"));
        delayQueue.put(new Student("学生6", dateFormat.parse("2016-11-10 16:05:10"), "6"));
        exec.execute(new Teacher(delayQueue, exec));
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //将消息从队列中移除
        Student remove = new Student();
        remove.setId("6");
        delayQueue.remove(remove);
        delayQueue.put(new Student("学生7", dateFormat.parse("2016-11-10 16:02:10"), "7"));
//        students.put(new Student("学生8", dateFormat.parse("2016-11-10 16:43:20"), "8"));
//        students.put(new Student("学生9", dateFormat.parse("2016-11-10 16:43:01"), "9"));
//        students.put(new Student("学生10", dateFormat.parse("2016-11-10 16:43:03"), "10"));
//        students.put(new Student("学生11", dateFormat.parse("2016-11-10 16:43:11"), "11"));
//        students.put(new Student("学生12", dateFormat.parse("2016-11-10 16:43:17"), "12"));
    }
}

测试结果:


考试开始……
学生1 设置时间=2016-11-10 16:02:00;执行时间=2016-11-10 16:02:00
学生7 设置时间=2016-11-10 16:02:00;执行时间=2016-11-10 16:02:00
学生5 设置时间=2016-11-10 16:03:00;执行时间=2016-11-10 16:03:00
学生4 设置时间=2016-11-10 16:06:00;执行时间=2016-11-10 16:06:00
学生3 设置时间=2016-11-10 16:08:00;执行时间=2016-11-10 16:08:00
学生2 设置时间=2016-11-10 16:09:00;执行时间=2016-11-10 16:09:00

在考试的过程中,若有学生终止考试(不提交试卷),或有新的学生开始考试,确定交卷时间,最后学生的交卷时间都会按序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值