Java中的LinkedBlockingQueue clear()方法
LinkedBlockingQueue是Java中一种基于链表实现的线程安全的阻塞队列,可以作为线程池中的任务存储队列。它具有以下特点:
- 实现了BlockingQueue接口,可以实现同步阻塞。
- 存储元素的顺序是FIFO(First In First Out)的原则,即先进入队列的元素先被取出。
在使用LinkedBlockingQueue时,有时需要清空队列内的元素,这时就需要调用clear()方法。本文将详细介绍LinkedBlockingQueue的clear()方法实现及使用。
clear()方法
clear()方法是LinkedBlockingQueue类的一个公用方法,其定义如下:
public void clear() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
head = lastNode(head, null);
if (!takeIndexIsNext)
removeAllNodes();
count = 0;
putIndex = takeIndex;
} finally {
lock.unlock();
}
}
该方法没有返回值,作用是清空队列内所有元素。
方法实现
1. 获取锁
首先,使用ReentrantLock获取锁,这样可以保证在清空队列的过程中,不受其他线程的干扰。
final ReentrantLock lock = this.lock;
lock.lock();
2. 修改head指向
然后,通过lastNode()方法获取队列的最后一个节点,将head指向该节点,从而将队列中的所有节点都断开与队列的链接。
head = lastNode(head, null);
lastNode()方法的实现如下:
static <E> Node<E> lastNode(Node<E> first, Node<E> last) {
for (;;) {
Node<E> n = first.next;
if (n == null)
return first;
if (last != null && n.next == null)
last.next = n;
last = first;
first = n;
}
}
3. 移除队列中所有节点
如果takeIndexIsNext(一个boolean变量,值为true表示takeIndex=putIndex+1,即队列为空;false表示队列不为空)为false,调用removeAllNodes()方法,依次断开与队列的链接,从而移除队列中所有节点。
if (!takeIndexIsNext)
removeAllNodes();
removeAllNodes()方法的实现如下:
void removeAllNodes() {
// assert lock.isHeldByCurrentThread();
for (Node<E> p, h = head; (p = h.next) != null; h = p) {
h.next = h;
p.item = null;
}
}
4. 重置队列相关变量
再把count设置为0、putIndex设置为takeIndex,即重置队列相关变量。
count = 0;
putIndex = takeIndex;
5. 释放锁
最后释放锁。
finally {
lock.unlock();
}
示例代码
下面是使用LinkedBlockingQueue的示例代码。将0~100的数字添加到队列中,然后清空队列并输出队列元素个数。
import java.util.concurrent.LinkedBlockingQueue;
public class Main {
public static void main(String[] args) {
LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>();
for (int i = 0; i <= 100; i++) {
queue.offer(i);
}
System.out.println("队列元素个数为:" + queue.size());
queue.clear();
System.out.println("清空后,队列元素个数为:" + queue.size());
}
}
输出结果如下:
队列元素个数为:101
清空后,队列元素个数为:0
结论
LinkedBlockingQueue的clear()方法是一个很方便的清空队列的方法,使用该方法可以很快地移除队列中所有元素,使得队列重新变为空。应该注意的是,在调用clear()方法时,需要保证线程安全,避免因为其他线程的干扰而出现异常情况。同时也需要注意,调用该方法后,队列中原有的元素将被全部清空,因此在使用时需要慎重考虑。