大家推荐个靠谱的公众号程序员探索之路,公众号内点击网赚获取彩蛋,大家一起加油,这个公众号已经接入图灵
这里面有其他文章的知识如有不懂请看其他文章
===============
1.LinkedBlockingQueue的属性
===============
/** The capacity bound, or Integer.MAX_VALUE if none
队列的容量
*/
private final int capacity;
/** Current number of elements
队列中的元素数量
*/
private final AtomicInteger count = new AtomicInteger();
/**
* Head of linked list.
* Invariant: head.item == null
队列头元素
*/
transient Node<E> head;
/**
* Tail of linked list.
* Invariant: last.next == null
队列尾部元素
*/
private transient Node<E> last;
/** Lock held by take, poll, etc
读锁
*/
private final ReentrantLock takeLock = new ReentrantLock();
/** Wait queue for waiting takes
如果队列是空是 那么会notEmpty.await方法使读线程等待
*/
private final Condition notEmpty = takeLock.newCondition();
/** Lock held by put, offer, etc
写锁
*/
private final ReentrantLock putLock = new ReentrantLock();
/** Wait queue for waiting puts
如果队列使满的话,那么会notFull.await方法使写线程等待
*/
private final Condition notFull = putLock.newCondition();
===============
2.LinkedBlockingQueue的Node内部类
===============
/**
* Linked list node class
*/
static class Node<E> {
//节点的元素
E item;
/**
* One of:
* - the real successor Node
* - this Node, meaning the successor is head.next
* - null, meaning there is no successor (this is the last node)
节点的下一个节点
*/
Node<E> next;
//构造器
Node(E x) { item = x; }
}
===============
3.LinkedBlockingQueue的构造器
===============
/**
* Creates a {@code LinkedBlockingQueue} with a capacity of
* {@link Integer#MAX_VALUE}.
这个也就是传说中的无界队列 其实也就是容量为Integer.MAX_VALUE的队列
*/
public LinkedBlockingQueue() {
this(Integer.MAX_VALUE);
}
/**
* Creates a {@code LinkedBlockingQueue} with the given (fixed) capacity.
*
* @param capacity the capacity of this queue
* @throws IllegalArgumentException if {@code capacity} is not greater
* than zero
指定容量的队列
*/
public LinkedBlockingQueue(int capacity) {
if (capacity <= 0) throw new IllegalArgumentException();
this.capacity = capacity;
//初始化一个空的对头和队尾
last = head = new Node<E>(null);
}
/**
* Creates a {@code LinkedBlockingQueue} with a capacity of
* {@link Integer#MAX_VALUE}, initially containing the elements of the
* given collection,
* added in traversal order of the collection's iterator.
*
* @param c the collection of elements to initially contain
* @throws NullPointerException if the specified collection or any
* of its elements are null
这个是你在初始化的时候可以传入一个集合 会把集合中的元素放入到队列中
这个构造器看完后的方法就明白了
*/
public LinkedBlockingQueue(Collection<? extends E> c) {
this(Integer.MAX_VALUE);
final ReentrantLock putLock = this.putLock;
putLock.lock(); // Never contended, but necessary for visibility
try {
int n = 0;
for (E e : c) {
if (e == null)
throw new NullPointerException();
if (n == capacity)
throw new IllegalStateException("Queue full");
enqueue(new Node<E>(e));
++n;
}
count.set(n);
} finally {
putLock.unlock();
}
}
===============
4.put方法
===============
/**
* Inserts the specified element at the tail of this queue, waiting if
* necessary for space to become available.
*
* @throws InterruptedException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public void put(E e) throws InterruptedException {
//e不能为null
if (e == null) throw new NullPointerException();
// Note: convention in all put/take/etc is to preset local var
// holding count negative to indicate failure unless set.
int c = -1;
//新建node对象
Node<E> node = new Node<E>(e);
final ReentrantLock putLock = this.putLock;
final AtomicInteger count = this.count;
putLock.lockInterruptibly();
try {
/*
* Note that count is used in wait guard even though it is
* not protected by lock. This works because count can
* only decrease at this point (all other puts are shut
* out by lock), and we (or some other waiting put) are
* signalled if it ever changes from capacity. Similarly
* for all other uses of count in other wait guards.
*/
//如果队列已满 那么写线程等待
while (count.get() == capacity) {
notFull.await();
}
//走到这里说明队列不是满的 那就把元素入队
enqueue(node);
//注意这里 队列中的元素已经+1 但是c = 入队之前的容量
c = count.getAndIncrement();
//这个if什么情况下会成立呢 如果写线程有很多个写线程都在 notFull的条件队列中 此时入队之后的队列元素还是
//小于对列容量 那么就可以再唤醒一个写线程
if (c + 1 < capacity)
notFull.signal();
} finally {
putLock.unlock();
}
//注意这个c是入队之前的容量 那么c == 0(注意head并不算队列中的元素
再后面出对方法中也是返回head.next) 就是说入队之前 队列是空的 那么就可以看下
//是否有读线程等待,也就是做一个读线程唤醒操作
if (c == 0)
signalNotEmpty();
}
/**
* Links node at end of queue.
*
* @param node the node
入队方法 其实就是把node放到末尾 LinkedBlockingQueue的属性last = node
*/
private void enqueue(Node<E> node) {
// assert putLock.isHeldByCurrentThread();
// assert last.next == null;
last = last.next = node;
}
/**
* Signals a waiting take. Called only from put/offer (which do not
* otherwise ordinarily lock takeLock.)
//读线程唤醒
*/
private void signalNotEmpty() {
final ReentrantLock takeLock = this.takeLock;
takeLock.lock();
try {
notEmpty.signal();
} finally {
takeLock.unlock();
}
}
===============
5.take方法
===============
/**
* 这个take和put方法套路都差不多
*/
public E take() throws InterruptedException {
E x;
int c = -1;
final AtomicInteger count = this.count;
final ReentrantLock takeLock = this.takeLock;
takeLock.lockInterruptibly();
try {
//如果 队列是空的 那么读线程等待
while (count.get() == 0) {
notEmpty.await();
}
//走到这里说明队列不是空的 那么就出对
x = dequeue();
c = count.getAndDecrement();
//同样的套路 如果出对前队列中的元素 大于1 那么可以再唤醒一个读线程
if (c > 1)
notEmpty.signal();
} finally {
takeLock.unlock();
}
//如果 在这个节点出对之前 队列是满的 可以唤醒写线程
if (c == capacity)
signalNotFull();
return x;
}
/**
* Removes a node from head of queue.
*
* @return the node
出对方法
可以看到 把head与队列断开关系 head = first(就是原head的next) 返回first的item
*/
private E dequeue() {
// assert takeLock.isHeldByCurrentThread();
// assert head.item == null;
Node<E> h = head;
Node<E> first = h.next;
h.next = h; // help GC
head = first;
E x = first.item;
first.item = null;
return x;
}
/**
* Signals a waiting put. Called only from take/poll.
//唤醒写线程
*/
private void signalNotFull() {
final ReentrantLock putLock = this.putLock;
putLock.lock();
try {
notFull.signal();
} finally {
putLock.unlock();
}
}
/**
* 读取队列首元素 不出对
* @return {[type]} [description]
*/
public E peek() {
if (count.get() == 0)
return null;
final ReentrantLock takeLock = this.takeLock;
takeLock.lock();
try {
Node<E> first = head.next;
if (first == null)
return null;
else
return first.item;
} finally {
takeLock.unlock();
}
}
/**
* 获取元素 当队列中没有元素 返回null
* @return {[type]} [description]
*/
public E poll() {
final AtomicInteger count = this.count;
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();
c = count.getAndDecrement();
if (c > 1)
notEmpty.signal();
}
} finally {
takeLock.unlock();
}
if (c == capacity)
signalNotFull();
return x;
}
/**
* 写入元素 当队列满是返回false
* @param {[type]} E e [description]
* @return {[type]} [description]
*/
public boolean offer(E e) {
if (e == null) throw new NullPointerException();
final AtomicInteger count = this.count;
if (count.get() == capacity)
return false;
int c = -1;
Node<E> node = new Node<E>(e);
final ReentrantLock putLock = this.putLock;
putLock.lock();
try {
if (count.get() < capacity) {
enqueue(node);
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();
}
} finally {
putLock.unlock();
}
if (c == 0)
signalNotEmpty();
return c >= 0;
}