关注可以查看更多粉丝专享blog~
线程安全的无界非阻塞队列,由单向链表实现,入队出队使用CAS来保证线程安全。
public int size() {
int count = 0;
// 循环遍历,效率低,由于是无锁算法,所以size在高并发情况下不准确
for (Node<E> p = first(); p != null; p = succ(p))
if (p.item != null)
// Collection.size() spec says to max out
if (++count == Integer.MAX_VALUE)
break;
return count;
}
(题外话:在判断字符串是否为空的时候惯用写法是(null == str || “”.equals(str))其实String的equals方法也是遍历字符串,建议使用(cs == null || cs.length() == 0),还有习惯用StringUtils的,org.apache.commons.lang3.StringUtils和org.springframework.util.StringUtils是不一样的,spring使用的是equals,lang3使用的是length,建议自己封装StringUtils去继承lang3,后期可以根据自己需要去修改继承或者覆盖方法)
public boolean offer(E e) {
// 为空直接抛出空指针
if (e == null) throw new NullPointerException();
final AtomicInteger count = this.count;
// 如果队列已满直接返回false
if (count.get() == capacity)
return false;
int c = -1;
Node<E> node = new Node<E>(e);
final ReentrantLock putLock = this.putLock;
// 获取put锁
putLock.lock();
try {
// 如果队列未满直接调用enqueue入队,count+1
if (count.get() < capacity) {
// put(E e)与offer区别在于put在获取可中断锁(putLock.lockInterruptibly();)
// count.get() == capacity时while阻塞,offer无阻塞直接返回
// enqueue方法: last = last.next = node;
enqueue(node);
c = count.getAndIncrement();
// 入队后如果队列未满则唤醒生产者
if (c + 1 < capacity)
notFull.signal();
}
} finally {
// 释放锁
putLock.unlock();
}
if (c == 0)
// 如果添加前队列为空则唤醒消费者消费当前入队元素
signalNotEmpty();
return c >= 0;
}
带优先级的无界阻塞队列,内部使用平衡二叉堆实现,默认使用对象的compareTo方法提供比较规则,可以自定义comparators。
private static <T> void siftUpComparable(int k, T x, Object[] array) {
Comparable<? super T> key = (Comparable<? super T>) x;
while (k > 0) {
int parent = (k - 1) >>> 1;
Object e = array[parent];
if (key.compareTo((T) e) >= 0)
break;
array[k] = e;
k = parent;
}
array[k] = key;
}
private static <T> void siftDownComparable(int k, T x, Object[] array, int n) {
if (n > 0) {
Comparable<? super T> key = (Comparable<? super T>)x;
int half = n >>> 1; // loop while a non-leaf
while (k < half) {
int child = (k << 1) + 1; // assume left child is least
Object c = array[child];
int right = child + 1;
if (right < n &&
((Comparable<? super T>) c).compareTo((T) array[right]) > 0)
c = array[child = right];
if (key.compareTo((T) c) <= 0)
break;
array[k] = c;
k = child;
}
array[k] = key;
}
}
/**
* PriorityBlockingQueue 示例
**/
public class PriorityBlockingQueueTest {
/**
* 实现Comparable接口,getDelay和compareTo方法
**/
@Data // lombok
static class Task implements Comparable<Task> {
private int priority = 0;
private String taskName;
/**
* 实现compareTo方法
**/
@Override
public int compareTo( Task o ) {
return this.priority >= o.priority ? 1 : -1;
}
}
public static void main( String[] args ) {
PriorityBlockingQueue<Task> tasks = new PriorityBlockingQueue<>();
Random random = new Random();
for (int i = 0; i < 10; i++) {
Task task = new Task();
task.setPriority(random.nextInt(10));
task.setTaskName("taskName" + i);
tasks.offer(task);
}
while (!tasks.isEmpty()) {
Task poll = tasks.poll();
System.out.println(poll);
}
}
}
无界阻塞延时队列,使用独占锁实现线程同步,队列中元素需要实现Delayed接口。
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)
// 如果leader不为null,则说明有其他县城在执行take操作,此时休眠自己
available.await();
else {
// 如果未过期切leader为null,则将leader设置为当前线程
Thread thisThread = Thread.currentThread();
leader = thisThread;
try {
// 休眠等待delay时间,这期间会释放锁,所以其他线程可以执行offer操作,也可以take阻塞自己,
// 这期间会释放锁,所以其他线程可以执行offer操作,也可以take阻塞自己,剩余时间过期后
// 当前线程会重新竞争到锁,然后重置leader线程为null
// 重新进入for循环这时候会发现队首元素已经过期了,则会直接返回队首元素
available.awaitNanos(delay);
} finally {
if (leader == thisThread)
leader = null;
}
}
}
}
} finally {
// 操作完成后将leader设置为null,如果队列还有元素,则唤醒条件等待队列中的队首线程进行操作
if (leader == null && q.peek() != null)
available.signal();
// 释放锁
lock.unlock();
}
}
public E poll() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
E first = q.peek();
if (first == null || first.getDelay(NANOSECONDS) > 0)
return null;
else
return q.poll();
} finally {
lock.unlock();
}
}
/**
* DelayQueueTest 示例
**/
public class DelayQueueTest {
/**
* 实现Delayed接口,getDelay和compareTo方法
**/
@Data // lombok
static class DelayQueueEle implements Delayed {
// 延时时间
private final int delayTime;
// 到期时间
private final long expire;
// 任务名称
private String taskName;
public DelayQueueEle( int delayTime, String taskName ) {
this.delayTime = delayTime;
this.taskName = taskName;
this.expire = System.currentTimeMillis() + delayTime;
}
/**
* 实现getDelay方法
**/
@Override
public long getDelay( TimeUnit unit ) {
return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
/**
* 实现compareTo方法
**/
@Override
public int compareTo( Delayed o ) {
return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
}
}
public static void main( String[] args ) {
// 创建delay队列
DelayQueue<DelayQueueEle> delayeds = new DelayQueue<>();
// 创建延时任务
Random random = new Random();
for (int i = 0; i < 10; i++) {
delayeds.offer(new DelayQueueEle(random.nextInt(500), "taskName:" + i));
}
// 依次取出并打印
DelayQueueEle ele;
// 循环,防止虚假唤醒,则不能打印全部元素
try {
for (; ; ) {
while ((ele = delayeds.take()) != null) {
System.out.println(ele);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
// 或者
// for (; ; ) {
// while ((ele = delayeds.poll()) != null) {
// System.out.println(ele);
// }
// }
}
}