太原网站建设案例,WordPress营销推广返佣插件,企业网站seo维护,wordpress安装多说概念
LinkedBlockingQueue是非固定容量队列#xff0c;内部是通过链表存放数据#xff0c;并通过两把互斥锁#xff08;分别为取时互斥锁和放时互斥锁#xff0c;这也是与ArrayBlockingQueue的本质区别#xff0c;这样可以提高性能#xff09;来控制访问数据的同步问题。…概念
LinkedBlockingQueue是非固定容量队列内部是通过链表存放数据并通过两把互斥锁分别为取时互斥锁和放时互斥锁这也是与ArrayBlockingQueue的本质区别这样可以提高性能来控制访问数据的同步问题。提供的方法与ArrayBlockingQueue基本是一致的下面只介绍下有差异的地方细节上看ArrayBlockingQueue的源码解读就行。 核心属性
/*** 阻塞队列元素封装为Node*/
static class NodeE {E item;NodeE next;Node(E x) { item x; }
}/** 指定队列的长度默认为Integer.MAX */
private final int capacity;/** 记录数据条数 */
private final AtomicInteger count new AtomicInteger();//指向链表头
transient NodeE head;
//指向链表尾
private transient NodeE last;/** 读锁 */
private final ReentrantLock takeLock new ReentrantLock();
private final Condition notEmpty takeLock.newCondition();/** 写锁 */
private final ReentrantLock putLock new ReentrantLock();
private final Condition notFull putLock.newCondition();2.1 写操作
// 写操作
public boolean offer(E e) {// 非空if (e null) throw new NullPointerException();// 拿到count记录当前数据条数final AtomicInteger count this.count;// 如果count达到了最大值if (count.get() capacity)// 链表满了添加失败直接返回。return false;// 声明int c -1;// 用当前元素创建一个新的NodeNodeE node new NodeE(e);// 写锁final ReentrantLock putLock this.putLock;putLock.lock();try {// 再次判断链表是否还有空间有则通过enqueue存入数据if (count.get() capacity) {// 数据存入操作enqueue(node);// 链表元素数量count加1c count.getAndIncrement();// 添加完数据之后长度依然小于最大长度链表还有存放空间唤醒其他阻塞的写线程 // 读写不互斥可能前面在执行时队列是满的但是读操作依然在进行if (c 1 capacity)notFull.signal();}} finally {putLock.unlock(); //解写锁}// 判断原先是否为空c为0表示原先链表为空读线程肯定都在阻塞所以此时需求唤醒阻塞的读线程if (c 0)signalNotEmpty();return c 0;
}// 插入数据到链表尾插法
private void enqueue(NodeE node) {last last.next node;
}2.2 读操作
public E poll() {final AtomicInteger count this.count;// 为0没数据退出if (count.get() 0)return null;E x null;int c -1;// 读锁final ReentrantLock takeLock this.takeLock;takeLock.lock();try {// 如果队列有数据 if (count.get() 0) {x dequeue();// count --c count.getAndDecrement();if (c 1)// c 1,说明还有数据唤醒其他阻塞的读线程notEmpty.signal();}} finally {takeLock.unlock();}if (c capacity)// 到这说明链接有空位唤醒写线程signalNotFull();return x;
}
// 从头部取数据
private E dequeue() {NodeE h head;NodeE first h.next;h.next h; // help GChead first;E x first.item;first.item null;return x;
}