// 延时队列的关键抽象方法
import java.util.concurrent.TimeUnit;
public interface MyDelayed {
long getDelay(TimeUnit unit);
}
/**
* 队列的抽象接口
*/
public interface MyQueue<E> {
boolean add(E e) throws Exception;
E take() throws Exception;
E peek();
void clear();
boolean isEmpty();
int getSize();
}
// 自定义环形数组,线程安全由上游保证
public class RingArray<E> {
private Object[] element;
private int head, tail, size, capacity;
RingArray(int capacity) {
this.capacity = capacity;
this.size = 0;
this.head = -1;
this.tail = 0;
element = new Object[capacity];
}
public void addToTail(E ele) {
if(size < capacity) {
head = (head + 1) == capacity ? 0 : head + 1;
element[head] = ele;
size ++;
}
}
public E removeFromTail() {
E ele = null;
if(size > 0) {
ele = (E)element[tail];
element[tail] = null;
tail = (tail + 1) == capacity ? 0 : tail + 1;
size --;
}
return ele;
}
public void clear() {
for (int i = 0; i < capacity; i ++) element[i] = null;
}
public E peek() {
return (E) element[tail];
}
public int getSize() {
return size;
}
public void print() {
for (int i = 0; i < capacity; i ++) {
if(element[i] != null) System.out.print(element[i] + ", ");
}
System.out.println();
}
@Override
public String toString() {
return this.size + " from " + this.head + " to " + this.tail;
}
}
// 延时队列的抽象类,提供了一些模板方法
import java.util.concurrent.locks.ReentrantLock;
public abstract class MyAbstractQueue<E> implements MyQueue<E> {
private final RingArray<E> array;
private final int capacity;
private final ReentrantLock lock = new ReentrantLock();
public MyAbstractQueue(int capacity) {
this.capacity = capacity;
array = new RingArray(capacity);
}
public RingArray<E> getArray() {
return array;
}
public ReentrantLock getLock() {
return lock;
}
public int getCapacity() {
return capacity;
}
@Override
public E peek() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return array.peek();
} finally {
lock.unlock();
}
}
@Override
public void clear() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
array.clear();
} finally {
lock.unlock();
}
}
@Override
public boolean isEmpty() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return getSize() == 0;
} finally {
lock.unlock();
}
}
@Override
public int getSize() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return array.getSize();
} finally {
lock.unlock();
}
}
}
// 一个非同步的延时队列
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class MyDelayQueueWithoutSyn<E extends MyDelayed> extends MyAbstractQueue<E> {
public MyDelayQueueWithoutSyn(int capacity) {
super(capacity);
}
public boolean add(E e) {
final ReentrantLock lock = getLock();
lock.lock();
try {
getArray().addToTail(e);
} finally {
lock.unlock();
}
return true;
}
public E take() {
final ReentrantLock lock = getLock();
lock.lock();
try {
E first = peek();
if(first == null) {
return null;
} else {
for (;;) {
if (first.getDelay(TimeUnit.NANOSECONDS) <= 0) {
return getArray().removeFromTail();
}
}
}
} finally {
lock.unlock();
}
}
}
//同步阻塞延时对列实现
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class MyDelayQueueWithSyn<E extends MyDelayed> extends MyAbstractQueue<E> {
private Condition fullCondition = getLock().newCondition();
private Condition emptyCondition = getLock().newCondition();
public MyDelayQueueWithSyn(int capacity) {
super(capacity);
}
public boolean add(E e) throws Exception {
final ReentrantLock lock = getLock();
lock.lock();
try {
while (getSize() == getCapacity()) {
fullCondition.await();
}
getArray().addToTail(e);
emptyCondition.signalAll();
} finally {
lock.unlock();
}
return true;
}
public E take() throws Exception {
final ReentrantLock lock = getLock();
lock.lock();
try {
while (getSize() == 0) {
emptyCondition.await();
}
fullCondition.signalAll();
for (;;) {
if (peek().getDelay(TimeUnit.NANOSECONDS) <= 0) {
return getArray().removeFromTail();
}
}
} finally {
lock.unlock();
}
}
}
// 测试方法
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
/**
* 自定义延时队列
* 同步延时队列
* 非同步延时队列
*/
public class MyDelayQueueTest {
public static void main(String[] args) throws Exception {
long start = System.currentTimeMillis();
//MyDelayQueueWithoutSyn queue = new MyDelayQueueWithoutSyn(10);
MyDelayQueueWithSyn queue = new MyDelayQueueWithSyn(10);
ExecutorService producer = Executors.newFixedThreadPool(2, new MyThreadFactory());
for(int i = 0; i < 100; i ++) {
final int index = i;
int mod = index % 2;
int random = new Random().nextInt(5);
final long deadLine = mod == 0 ? 250 * random : 500 * random;
producer.submit(() -> {
Message<Integer> m = new Message<>(index, deadLine);
try {
queue.add(m);
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
ExecutorService consumer = Executors.newSingleThreadExecutor();
consumer.submit(() -> {
while (!queue.isEmpty()) {
try {
System.out.println("get => " + queue.take());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
producer.shutdown();
consumer.shutdown();
System.out.println(System.currentTimeMillis() - start);
}
static class MyThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
return thread;
}
}
static class Message<T> implements MyDelayed {
long deadLine;
T t;
Message(T t, long deadLine) {
this.t = t;
setDeadLine(deadLine);
}
public void setDeadLine(long deadLine) {
this.deadLine = deadLine + System.currentTimeMillis();
}
public long getDeadLine() {
return deadLine;
}
@Override
public long getDelay(TimeUnit unit) {
return deadLine - System.currentTimeMillis();
}
@Override
public String toString() {
return "Message{" +
"deadLine=" + deadLine +
", t=" + t +
'}';
}
}
}