此类实现了BlockingQueue接口,同时继承了父类AbstractQueue,父类里实现了几个基本方法的调用
add(E e),通过子类的offer(e)具体实现
remove(),通过子类的poll()具体实现
element(),通过子类的peek()具体实现,这几个是常用方法
在LinkedBlockingQueue中,先定义了个Node内部类,这个类是队列中存储的具体的节点类,所以的通过泛型定义的类型都会封装成Node类存储在队列里
static class Node<E> { //加static 可以在类中直接定义,不用加外部类名的前缀
E item; //定义某个泛型类型变量,存储具体的值
Node<E> next; //队列里链表存储机制,这个是定义下一个的节点
Node(E x) { item = x; }
}
final int capacity; //定义此队列的长度,默认是Integer的最大长度Integer.MAX_VALUE
final AtomicInteger count = new AtomicInteger(0); //当前队列的已有个数,定义成AtomicInteger可以在底层实现CAS的原子操作
signalNotEmpty()和signalNotFull()方法在多线程情况下,生产者和消费者模式里进行唤醒操作,类似Object中的notify()方法
队列真实添加节点的方法,所有的入队都会调用
private void enqueue(Node<E> node) {
last = last.next = node; //这句代码相当于 last.next = node; last = last.next; 把节点赋值给最后节点的下一个,最后节点往后推一个
}
与之对应的是所有的出队都会调用的方法,取头结点指向的节点
private E dequeue() {
Node<E> h = head;
Node<E> first = h.next; //获取头结点的下一个节点 first
h.next = h; // help GC //释放最开始的头结点
head = first; //把first当做头结点
E x = first.item;
first.item = null; //清空头结点的具体值
return x;
}
进队方法,基本上进队都是类似操作
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
int c = -1;
Node<E> node = new Node(e);
final ReentrantLock putLock = this.putLock;
final AtomicInteger count = this.count;
putLock.lockInterruptibly();
try {
while (count.get() == capacity) { //如果队列已满,入队锁里的notFull条件生效,开始等待
notFull.await();
}
enqueue(node);
c = count.getAndIncrement(); //没加这个节点之前,队列中节点个数
if (c + 1 < capacity) //加完这个节点后如果还有空地,唤醒一个入队锁里的在notFull条件等待的线程
notFull.signal();
} finally {
putLock.unlock();
}
if (c == 0) //如果在加入这个节点前,队列为空,则唤醒一个在出队锁里,在notEmpty条件等待的线程
signalNotEmpty();
}
出队方法,基本上出队都是类似操作
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条件生效,开始等待
notEmpty.await();
}
x = dequeue();
c = count.getAndDecrement();
if (c > 1) //取出这个节点后如果队列还有值,唤醒一个出队锁里的在notEmpty条件等待的线程
notEmpty.signal();
} finally {
takeLock.unlock();
}
if (c == capacity) //如果在取出这个节点前,队列是满的,则唤醒一个在入队锁里,在notFull条件等待的线程
signalNotFull();
return x;
}
其他出队入队的方法类似这两个方法,就不多说了。
这个类主要是注意这个队列是用链表进行存储,头结点的item是null,next指向了第一个节点。在多线程同步的时候用了ReentrantLock,定义了出队锁和入队锁,每个所都有自己的condition,所以唤醒的时候回相对精确唤醒某种类型的await。用了AtomicInteger对象做计数器,这个类实现了加减的CAS操作,操作返回的是之前的值。
分享到:
相关推荐
1. 链表结构:`LinkedBlockingQueue`内部由两个节点类`Node`组成,一个表示元素,另一个表示等待的线程。这种设计使得插入和移除操作的时间复杂度为O(1)。 2. 阻塞机制:`LinkedBlockingQueue`通过`Lock`和`...
文件中的类可能定义了一个简单的单向链表节点,包括节点的数据成员(如数据item和指向下一个节点的引用next)以及可能的辅助方法,例如插入新节点、删除节点或者遍历链表等。这些方法需要正确处理并发访问,以确保...
《LinkedBlockingQueue与ConcurrentLinkedQueue的比较与应用》 在Java并发编程中,队列是一种重要的数据结构,尤其在多线程环境下的任务调度和数据传递中扮演着关键角色。LinkedBlockingQueue和...
### 并发队列 ConcurrentLinkedQueue 和阻塞队列 LinkedBlockingQueue 用法详解 #### 一、并发队列 ConcurrentLinkedQueue 概述 `ConcurrentLinkedQueue` 是 Java 并发包 `java.util.concurrent` 提供的一个高性能...
`LinkedBlockingQueue`的内部实现基于两个主要的链接节点类:`Node`和`LinkedBlockingQueue.E`. `Node`用于存储元素,`E`是`Node`的一个内部静态类,实现了`Runnable`接口,用于线程的唤醒。每个节点包含一个元素和...
LinkedBlockingQueue使用链表方式实现的阻塞队列,链表的节点是通过内部类Node实现的。Node类中有两个变量,一个是储存数据的变量item,一个是指向链表的下一个节点的引用next。链表的头节点head和尾节点last是在...
在Java的并发编程中,JDK提供的容器类库扮演了重要角色,其中`java.util.concurrent`包下的`BlockingQueue`接口及其实现类是多线程环境下数据同步的重要工具。本篇文章将深入探讨`LinkedBlockingQueue`,这是一个...
它们都继承自AbstractQueue类,并实现了BlockingQueue接口,提供了线程安全的队列操作。 ArrayBlockingQueue实现原理: ArrayBlockingQueue内部使用数组存储元素,使用ReentrantLock来保证线程安全,使用Condition...
要实现这一特性,我们通常会自定义队列的元素类,并重写`equals()`和`hashCode()`方法,确保元素比较时的唯一性。同时,队列在插入元素时会进行检查,如果发现新元素与队列中已有的元素相同,则插入操作会被阻止。 ...
在Java中,阻塞队列(BlockingQueue)是一个很好的实现生产者/消费者模式的工具,而LinkedBlockingQueue则是Java并发包(java.util.concurrent)中提供的一个具体实现。 LinkedBlockingQueue是一个基于链表结构的...
Java中的`LinkedBlockingQueue`和`ArrayBlockingQueue`都是`java.util.concurrent`包下的线程安全队列,它们都实现了`BlockingQueue`接口,提供了一种高效、线程安全的数据同步方式。这两种队列在很多方面都有相似之...
《Java多线程环境下慎用`LinkedBlockingQueue`的`stream`遍历——揭秘JDK BUG》 在Java编程中,线程安全是多线程编程的重要考量因素,而`LinkedBlockingQueue`作为Java并发包中的一个线程安全队列,因其高效的性能...
LinkedBlockingQueue :由容器/列表支持的有界阻塞队列 ConcurrentRingBuffer :由片支持的有界无锁队列 安装 go get - u github . com / theodesp / blockingQueues 用法 非阻塞API queue , _ := NewArrayBlock
3. BlockingQueue和BlockingDeque:这两个接口提供了线程安全的队列操作,如ArrayBlockingQueue、LinkedBlockingQueue和PriorityBlockingQueue实现了BlockingQueue接口,而LinkedBlockingDeque实现了BlockingDeque...
此外,Java提供了BlockingQueue接口和其实现(如ArrayBlockingQueue、LinkedBlockingQueue等),它们提供了线程安全的数据结构,方便线程间的异步通信。 线程优先级是另一个重要概念,Java中线程的优先级范围是1...
### Java线程池管理类:Executors_ #### 概述 `java.util.concurrent.Executors` 是Java并发编程中一个非常重要的工具类,主要用于创建不同类型的线程池对象。通过使用`Executors`类,开发者可以方便地管理和控制...
- `LinkedBlockingQueue`、`PriorityQueue`等队列类,满足不同同步和排序需求。 - `NavigableSet`和`NavigableMap`接口,提供了更丰富的导航和查找功能。 理解并熟练运用这些知识点对于Java开发者来说至关重要,...
2. **LinkedBlockingQueue**:基于链表实现的有界队列,队列的大小默认为Integer.MAX_VALUE,同样遵循FIFO原则。相比于ArrayBlockingQueue,它的吞吐量通常更高,但在空间占用上更大。 3. **SynchronousQueue**:一...