ArrayBlockingQueue是concurrent包提供的一个线程安全的队列,由一个数组来保存队列元素.通过
takeIndex和
putIndex来分别记录出队列和入队列的下标,以保证在出队列时
不进行元素移动.
//在出队列或者入队列的时候对takeIndex或者putIndex进行累加,如果已经到了数组末尾就又从0开始,保证数组的循环使用.
final int inc(int i) {
return (++i == items.length) ? 0 : i;
}
//入队列操作
private void insert(E x) {
items[putIndex] = x;
putIndex = inc(putIndex);
++count;
notEmpty.signal();//唤醒等待的出队线程
}
//使用offer入队列,如果队列已满就立即返回false
public boolean offer(E e) {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (count == items.length)
return false;
else {
insert(e);
return true;
}
} finally {
lock.unlock();
}
}
//使用put入队列的话,如果队列已满当前线程就等待然后释放锁,直到被notFull唤醒,再重新检查,直到成功插入队列
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == items.length)
notFull.await();
insert(e);
} finally {
lock.unlock();
}
}
//出队列操作
private E extract() {
final Object[] items = this.items;
E x = this.<E>cast(items[takeIndex]);
items[takeIndex] = null;
takeIndex = inc(takeIndex);
--count;
notFull.signal();//唤醒等待入队的线程
return x;
}
//poll出队是不需要等待的,如果当前队列是空就直接返回null
public E poll() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return (count == 0) ? null : extract();
} finally {
lock.unlock();
}
}
//take就跟put一样,如果队列是空的就等待直到被notEmpty唤醒
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)
notEmpty.await();
return extract();
} finally {
lock.unlock();
}
}
最后需要注意的就是带
超时唤醒的是
offer和
poll而不是put和take
分享到:
相关推荐
- **CopyOnWriteArrayList/CopyOnWriteArraySet**:适用于读多写少的情况,读操作无需加锁,写操作则复制整个集合。 7. **源码分析** - PDF文档和源码结合可以帮助读者深入理解多线程设计模式的实际应用,通过...
Java多线程编程实战指南(呵心篇)是一份深入探讨Java并发编程的资源,它提供了丰富的源码示例来帮助开发者理解并掌握多线程技术。在这个领域,Java提供了强大的支持,使得开发者能够构建高性能、高并发的应用程序。...
Java中可以使用`BlockingQueue`接口及其实现(如`ArrayBlockingQueue`)来实现此模式,通过`put()`和`take()`方法控制生产和消费的同步。 2. **线程池模式**:Java中的`ExecutorService`和`ThreadPoolExecutor`是...
ArrayBlockingQueue LinkedBlockingQueue LinkedBlockingDeque :scroll: 主要介绍LeetCode上面的算法译文,以及面试过程中遇到的实际编码问题总结。 :locked: :file_folder: :laptop: :globe_showing_Asia-...
- **ArrayBlockingQueue**:基于数组的有界阻塞队列。 - **LinkedBlockingQueue**:基于链表的阻塞队列,可以设置容量也可以不限制。 以上总结了多线程面试中的常见问题及解决方案,包括但不限于`synchronized`...
Java多线程是Java开发中的核心技能之一,尤其在面试中,对于一线大厂的面试者来说,深入理解和掌握多线程的相关知识点至关重要。以下是一些关键的Java多线程面试知识点: 1. **自旋锁**:自旋锁是一种等待机制,当...
关键在于同步和阻塞机制,Java中可以使用BlockingQueue接口来实现,例如ArrayBlockingQueue。 2. **单例模式**:在多线程环境中,确保一个类只有一个实例非常重要,以避免资源竞争和不一致状态。Java中可以使用双重...
它们在添加或删除元素时会创建一个新的底层数组,然后将原有数组的引用更改为新数组,这样在读取时不会阻塞写操作,适用于读多写少的场景。 3. **BlockingQueue**: 这是一种线程安全的队列,主要用于生产者-消费者...
本书《Java Concurrency In Practice》是Java并发编程的经典之作,由Brian Goetz、Tim Peierls、Joshua Bloch、David Holmes和Doug Lea等多位专家共同撰写,为开发者提供了深入理解并有效利用Java并发工具的全面指南...
2. 并发容器及典型源码分析并发容器是Java并发编程中不可或缺的一部分,它们提供了线程安全的数据结构,可以高效地处理多线程环境下的数据共享。以下是一些重要的并发容器: 2.1 ConcurrentHashMap并发哈希映射表,...