import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
import org.junit.Test;
import com.icil.pinpal.payment.common.utils.NumberUtils;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;public classOrderPayTimeOut {/**
* 3个线程:
* 线程1:向队列中添加数据
* 线程2:从队列中取出数据
* 线程3:向队列中添加数据
* @throws Exception*/@Testpublic voidtestDelayQueue() throws Exception {
ExecutorService executor= Executors.newFixedThreadPool(3); //创建线程池并返回ExecutorService实例
DelayQueue queue = new DelayQueue<>();
FutureTask add = add(queue,"before",3);
FutureTask take =take(queue);
Thread.sleep(100l);
FutureTask add1 = add(queue,"later",1);
FutureTask add2 = add(queue,"then",1);
executor.execute(add);//执行任务
executor.execute(add1); //执行任务
executor.execute(add2); //执行任务
executor.execute(take);while(true) {}
}/**
* 单线程测试
* @description: 延时队列测试
* @author: hh*/@Testpublic voidtestRun() throws InterruptedException {
PaylogX item1= new PaylogX("item1", 1, TimeUnit.MINUTES);
PaylogX item2= new PaylogX("item2",3, TimeUnit.MINUTES);
PaylogX item3= new PaylogX("item3",5, TimeUnit.MINUTES);
DelayQueue queue = new DelayQueue<>();
queue.offer(item1);
queue.offer(item2);
queue.offer(item3);
System.out.println("begin time:" +LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));for (int i = 0; i < 3; i++)
{
PaylogX paylogX=queue.take();
System.out.format("name:{%s},time:{%s} date:{%s}\n",paylogX.oTitle,paylogX.timeStamp, LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME));
}
}/**
* 添加数据到队列
* @param queue
* @return*/
private FutureTask add(DelayQueue queue,String name,longexpireTime) {
Callable callable1=new Callable() {
@OverridepublicString call() throws Exception {
System.err.println(name+"开始添加数据!!");
IntStream.range(0, 1000).forEach(i->{
PaylogX paylogX= new PaylogX(name+i, expireTime+new Random().nextInt(10), TimeUnit.SECONDS);try{
Thread.sleep(100l);
}catch(InterruptedException e) {
e.printStackTrace();
}
queue.put(paylogX);
});
System.err.println(name+"添加数据结束!!");return null;
}
};
FutureTask futureTask1 = new FutureTask(callable1);returnfutureTask1;
}/**
* 从队列中取出数据
* @param queue
* @return*/
private FutureTask take(DelayQueuequeue) {
Callable callable1=new Callable() {
@OverridepublicString call() throws Exception {while (true) {
PaylogX paylogX=queue.take();//queue.remove(take);
System.out.format("name:{%s},time:{%s} date:{%s}\n",paylogX.oTitle,paylogX.timeStamp, LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME));
}
}
};
FutureTask futureTask1 = new FutureTask(callable1);returnfutureTask1;
}
@NoArgsConstructor
@Data
@ToStringclassPaylogX implements Delayed{private String _id=NumberUtils.genNO() ; //uuid
privateString oTitle ;private long timeStamp=newDate().getTime();private transient long delayTime; 延迟时长,这个是必须的属性因为要按照这个判断延时时长。
public PaylogX(String oTitle ,longdelayTime,TimeUnit unit) {this.oTitle=oTitle;this.delayTime = System.currentTimeMillis() + (delayTime > 0? unit.toMillis(delayTime): 0);
}
@Overridepublic intcompareTo(Delayed o) {
PaylogX delayed=(PaylogX)o;long diff = this.delayTime-delayed.delayTime;if (diff <= 0) {//改成>=会造成问题
return -1;
}else{return 1;
}
}
@Overridepublic longgetDelay(TimeUnit unit) {return this.delayTime -System.currentTimeMillis();
}public void setDelayTime(longdelayTime) {this.delayTime =delayTime;
}
}
}