线程安全的、无界(写不阻塞)、阻塞、延迟队列
(源码)线程安全的(使用ReentrantLock)无界:
// 添加元素的方法
public boolean offer(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
q.offer(e);
if (q.peek() == e) {
leader = null;D
available.signal();
}
return true;
} finally {
lock.unlock();
}
}
(源码)无界(添加元素使用的是PriorityQueue类中的offer,写不阻塞):
public boolean offer(E e) {
if (e == null)
throw new NullPointerException();
modCount++;
int i = size;
if (i >= queue.length)
grow(i + 1);
size = i + 1;
if (i == 0)
queue[0] = e;
else
siftUp(i, e);
return true;
}
(源码)阻塞队列,如果peek获取不到数据,available.await()会进入阻塞状态
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
for (;;) {
E first = q.peek();
if (first == null)
available.await();
else {
long delay = first.getDelay(NANOSECONDS);
if (delay <= 0)
return q.poll();
first = null; // don't retain ref while waiting
if (leader != null)
available.await();
else {
Thread thisThread = Thread.currentThread();
leader = thisThread;
try {
available.awaitNanos(delay);
} finally {
if (leader == thisThread)
leader = null;
}
}
}
}
} finally {
if (leader == null && q.peek() != null)
available.signal();
lock.unlock();
}
}
延迟队列,使用DelayQueue,必须实现Delayed接口,实现的接口中有两个参数:延迟时间,优先级规则,take方法会根据规则按照优先级执行(源码)
public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
/**
* 优先级规则:两个任务比较,时间短的优先执行
*/
@Override
public int compareTo(Delayed o) {
long f = this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS);
return (int) f;
}
示例
public class T03_DelayQueue {
public static void main(String[] args) throws InterruptedException {
BlockingQueue<DelayTask> q = new DelayQueue();
Thread thread1 = new Thread(()->{
System.out.println("thread1");
},"线程1");
Thread thread2 = new Thread(()->{
System.out.println("thread2");
},"线程2");
DelayTask t1 = new DelayTask(1000,thread2);
DelayTask t2 = new DelayTask(3000,thread1);
q.offer(t1);
q.offer(t2);
for (int i = 0; i < 2; i++) {
DelayTask take = q.take();
// 开启线程,执行任务
take.data.start();
System.out.println(take.toString());
}
}
}
class DelayTask implements Delayed{
long delayTime; // 延迟时间
long expire; // 过期时间
Thread data;
public DelayTask(long delayTime,Thread data) {
this.delayTime = delayTime;
this.data = data;
// 过期时间 = 当前时间 + 延迟时间
this.expire = System.currentTimeMillis() + delayTime;
}
/**
* 优先级规则:两个任务比较,时间短的优先执行
*/
@Override
public int compareTo(Delayed o) {
long f = this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS);
return (int) f;
}
/**
* 剩余时间 = 到期时间 - 当前时间
*/
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@Override
public String toString() {
return "线程:"+data.getName()+"执行;延迟时间为:"+ delayTime+";";
}
}
应用场景
1,程序中按照时间顺序执行计划的调度任务,例如数据的归集,首先采集的数据归集到小时表,然后归集到天表,然后月表、年表。
2,从A、B两个系统获取数据,B系统中的数据依赖A系统,这种情况下可以使用DelayQueue队列使用。