1. 简单的延时消费队列单元测试,将2个任务添加到队列中,然后消费,代码如下:
package com.robinboot.facade;
import com.robinboot.service.task.DelayRunnable;
import com.robinboot.service.task.DelayRunnable;
import com.robinboot.service.task.TaskManager;
import org.apache.log4j.Logger;
import org.junit.Before;
import org.junit.Test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @auther: TF12778
* @date: 2020/11/26 11:22
* @description:简单的延时消费队列单元测试,将2个任务添加到队列中,然后消费
*/
public class TaskTest extends BaseTest{
public static final Logger logger=Logger.getLogger(TaskTest.class);
ExecutorService singlePooling = Executors.newSingleThreadExecutor();
DelayRunnable delayTask = new DelayRunnable();
@Before
public void tastttt1() {
singlePooling.submit(delayTask);
}
@Test
public void tastttt() {
delayTask.put(new Runnable() {
@Override
public void run() {
System.out.println("delayTask------1");
}
}, 1);
delayTask.put(new Runnable() {
@Override
public void run() {
System.out.println("delayTask------2");
}
}, 5);
}
}
执行结果:
二. DelayRunnable 主要作用:
声明了一个延时任务队列,将任务添加到任务队列中,每100ms取出一个任务去执行, 任务提交到线程池
package com.robinboot.service.task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.*;
/**
* @auther: TF12778
* @date: 2020/11/26 11:02
* @description:声明了一个延时任务队列,将任务添加到任务队列中,每100ms取出一个任务去执行, 任务提交到线程池
*/
public class DelayRunnable implements Runnable {
private static final Logger logger = LoggerFactory.getLogger(DelayRunnable.class);
private ExecutorService pooling = new ThreadPoolExecutor(2, 3, 100, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(10));
private DelayQueue<DelayedTask<Runnable>> dQueue = new DelayQueue<>();
private volatile boolean started = true;
public void put(Runnable r, long delay){
dQueue.add(new DelayedTask<Runnable>(r, delay));
}
@Override
public void run() {
DelayedTask<Runnable> task = null;
while (started){
try {
task = dQueue.poll(100, TimeUnit.MILLISECONDS); // 每100ms取出一个任务去执行
}catch (InterruptedException e){
logger.warn("dQueue thread is interrupted.",e);
}
if(task != null){
logger.info("tasks in delayQueue: " + dQueue.size());
fireTask(task.getItem());
task = null;
}
}
}
public void stop(){
started = false;
}
private void fireTask(Runnable r){
this.pooling.submit(r); // 任务提交到线程池
}
}
package com.robinboot.service.task;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
/**
* @auther: sww
* @date: 2020/11/26 10:57
* @description:
*/
public class DelayedTask<T> implements Delayed {
/**
* Sequence number to break scheduling ties, and in turn to guarantee FIFO order among tied
* entries.
*/
private static final AtomicLong SEQUENCER = new AtomicLong(0);
/** The time the task is enabled to execute in nanoTime units */
private long time;
/** Sequence number to break ties FIFO */
private final long SEQUENCE_NUMBER;
/** Base of nanosecond timings, to avoid wrapping */
private static final long NANO_ORIGIN = System.nanoTime();
private final T item;
public DelayedTask(T submit, long timeout) {
this.time = now() + TimeUnit.NANOSECONDS.convert(timeout, TimeUnit.MILLISECONDS);
this.item = submit;
this.SEQUENCE_NUMBER = SEQUENCER.getAndIncrement();
}
public T getItem() {
return this.item;
}
final static long now() {
return System.nanoTime() - NANO_ORIGIN;
}
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(time - now(), TimeUnit.NANOSECONDS);
}
@Override
public int compareTo(Delayed o) {
if(o == this){
return 0;
}
if(o instanceof DelayedTask){
DelayedTask t = (DelayedTask) o;
long diff = this.time - t.time;
if(diff < 0){
return -1;
}else if(diff > 0){
return 1;
}else if(SEQUENCE_NUMBER < t.SEQUENCE_NUMBER){
return -1;
}else {
return 1;
}
}
long d = (getDelay(TimeUnit.NANOSECONDS) - o.getDelay(TimeUnit.NANOSECONDS));
return (d == 0) ? 0 : ((d < 0) ? -1 : 1);
}
@Override
public boolean equals(Object object){
if(object ==null || !(object instanceof DelayedTask)){
return false;
}
return this.getItem().equals(((DelayedTask<T>)object).getItem());
}
}