手动设计一个延时队列,需要用到delayqueue,AtomicInteger等多线程知识。按照生产者消费者模式设计。
因为我在测试timeunit枚举类时候,忘记统一单位导致后面程序可以正常运行,就是得不到正确结果。解决方法,统一时间单位,
将TimeUnit.MINUTES修改为TimeUnit.MILLISECONDS
总结:再查找可以正常运行无报错的程序的bug时候
1 尝试分块进行测试,确保分块测试没问题
2 找到正确实例,分块将自己的代码块带入正确实例进行替换验证,确保每块代码块可以正常运行,
3 找到正确实例,分块(块可以从大到小)将正确实例带入自己代码中,直到找到可以保证正常运行的代码位置,对比两者区别
现在将正确代码共享
package javatest;
import java.text.DateFormat;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class MyDelayQueue {
//线程安全的,自动产生编号
static AtomicInteger messageno = new AtomicInteger(1);
public static void main(String[] args) {
DelayQueue<DelayQueueItem> queue = new DelayQueue<>();
producer(queue,"生产者1");
producer(queue,"生产者2");
producer(queue,"生产者3");
producer(queue,"生产者4");
consumer(queue);
consumer(queue);
consumer(queue);
}
private static void consumer(DelayQueue<DelayQueueItem> queue) {
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
DelayQueueItem item = null;
try {
item = queue.take();
System.out.println(item.toString());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
private static void producer(DelayQueue<DelayQueueItem> queue, String name) {
new Thread() {
@Override
public void run() {
while(true) {
Long time = 100L*(new Random().nextInt(10) + 1);
//适当延时,不至于插入队列太快
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String message = String.format("队列名:%s,消息编号:%d,发送时间:%s,延时时间:%s 毫秒",
name, //队列名字,由main传过来
messageno.getAndIncrement(), //由全局变量传来,这个变量线性安全,类似于i++
DateFormat.getDateTimeInstance().format(new Date()), //java8新增加的时间函数
time);
DelayQueueItem item = new DelayQueueItem(time,message);
queue.put(item);
//System.out.println("test:"+item.toString());
}
}
}.start();
}
static class DelayQueueItem implements Delayed {
//delayqueue规定放入队列中的元素必须实现delayed接口并且重写方法
//每个元素的超时时间(延时时间)
Long time = System.currentTimeMillis();
//放入队列的消息体
String message;
public DelayQueueItem() {
super();
}
public DelayQueueItem(Long time, String message) {
super();
this.time += time;
this.message = message;
}
//timeunit枚举类提供一些时间计算函数,
//convert函数计算延时时间,返回Long类型。(this.time - System.currentTimeMillis())*TimeUnit.MILLISECONDS
//其中 TimeUnit.MILLISECONDS = 1 表示参与运算的单位是毫秒
// TimeUnit.SECONDS = 1000
// TimeUnit.MINUTES = 6000
// TimeUnit.HOURS = 3600000
@Override
public long getDelay(TimeUnit unit) {
// TODO Auto-generated method stub
return unit.convert(this.time - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
//接受运用delayed类型,属于多态的一种体现
//compareTo函数为排序提供了比较策略,这个属于类外比较
@Override
public int compareTo(Delayed o) {
// TODO Auto-generated method stub
if (this.getDelay(TimeUnit.MILLISECONDS)>o.getDelay(TimeUnit.MILLISECONDS)) return 1;
else if (this.getDelay(TimeUnit.MILLISECONDS)<o.getDelay(TimeUnit.MILLISECONDS)) return -1;
return 0;
}
@Override
public String toString() {
return "time=" + time + ", message=" + message + "]";
}
}
}