Java 阻塞佇列(BlockingQueue)的內部實現原理
阻塞佇列原理:
其實阻塞佇列實現阻塞同步的方式很簡單,使用的就是: lock + 多個條件(condition)阻塞控制。
使用BlockingQueue封裝了根據條件阻塞執行緒的過程,而我們就不用關心繁瑣的await/signal操作了。
下面是Jdk 1.7中ArrayBlockingQueue部分程式碼:
public ArrayBlockingQueue(int capacity, boolean fair) {
if (capacity <= 0)
throw new IllegalArgumentException();
//建立陣列
this.items = new Object[capacity];
//建立鎖和阻塞條件
lock = new ReentrantLock(fair);
notEmpty = lock.newCondition();
notFull = lock.newCondition();
}
//新增元素的方法
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == items.length)
notFull.await();
//如果佇列不滿就入隊
enqueue(e);
} finally {
lock.unlock();
}
}
//入隊的方法
private void enqueue(E x) {
final Object[] items = this.items;
items[putIndex] = x;
if (++putIndex == items.length)
putIndex = 0;
count++;
notEmpty.signal();
}
//移除元素的方法
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)
notEmpty.await();
return dequeue();
} finally {
lock.unlock();
}
}
//出隊的方法
private E dequeue() {
final Object[] items = this.items;
@SuppressWarnings("unchecked")
E x = (E) items[takeIndex];
items[takeIndex] = null;
if (++takeIndex == items.length)
takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
notFull.signal();
return x;
使用例子:
阻塞佇列的最長使用的例子就是生產者消費者模式,也是各種實現生產者消費者模式方式中首選的方式。使用者不用關心什麼阻塞生產,什麼時候阻塞消費,使用非常方便,程式碼如下:
package bigtree.com;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
public class BlockingQueueTest {
public static class Producer implements Runnable{
private final BlockingQueue<Integer> blockingQueue;
private volatile boolean flag;
private Random random;
public Producer(BlockingQueue<Integer> blockingQueue) {
this.blockingQueue = blockingQueue;
flag=false;
random=new Random();
}
public void run() {
while(!flag){
int info=random.nextInt(100);
try {
blockingQueue.put(info);
System.out.println(Thread.currentThread().getName()+" produce "+info);
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void shutDown(){
flag=true;
}
}
public static class Consumer implements Runnable{
private final BlockingQueue<Integer> blockingQueue;
private volatile boolean flag;
public Consumer(BlockingQueue<Integer> blockingQueue) {
this.blockingQueue = blockingQueue;
}
public void run() {
while(!flag){
int info;
try {
info = blockingQueue.take();
System.out.println(Thread.currentThread().getName()+" consumer "+info);
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void shutDown(){
flag=true;
}
}
public static void main(String[] args){
BlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<Integer>(10);
Producer producer=new Producer(blockingQueue);
Consumer consumer=new Consumer(blockingQueue);
//建立5個生產者,5個消費者
for(int i=0;i<10;i++){
if(i<5){
new Thread(producer,"producer"+i).start();
}else{
new Thread(consumer,"consumer"+(i-5)).start();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
producer.shutDown();
consumer.shutDown();
}
}
相關文章
- 阻塞佇列 BlockingQueue佇列BloC
- BlockingQueue的作用以及實現的幾個常用阻塞佇列原理BloC佇列
- Java併發系列 — 阻塞佇列(BlockingQueue)Java佇列BloC
- Java併發包原始碼學習系列:阻塞佇列BlockingQueue及實現原理分析Java原始碼佇列BloC
- 阻塞佇列BlockingQueue(三)--DelayQueue佇列BloC
- Java執行緒(篇外篇):阻塞佇列BlockingQueueJava執行緒佇列BloC
- Java併發指南11:解讀 Java 阻塞佇列 BlockingQueueJava佇列BloC
- Java BlockingQueue 阻塞佇列[用於多執行緒]JavaBloC佇列執行緒
- 阻塞佇列一——java中的阻塞佇列佇列Java
- Java阻塞佇列中的異類,SynchronousQueue底層實現原理剖析Java佇列
- Java阻塞佇列執行緒集控制的實現Java佇列執行緒
- 阻塞佇列 BlockingQueue(二)--ArrayBlockingQueue與LinkedBlockingQueue佇列BloC
- Java中的阻塞佇列Java佇列
- 解讀 Java 併發佇列 BlockingQueueJava佇列BloC
- 佇列、阻塞佇列佇列
- java併發程式設計工具類JUC第一篇:BlockingQueue阻塞佇列Java程式設計BloC佇列
- [Java併發程式設計實戰] 阻塞佇列 BlockingQueue(含程式碼,生產者-消費者模型)Java程式設計佇列BloC模型
- 自己動手實現一個阻塞佇列佇列
- 阻塞佇列佇列
- java多執行緒:執行緒池原理、阻塞佇列Java執行緒佇列
- mysqldump的內部實現原理MySql
- 乾貨|解讀Java併發佇列BlockingQueueJava佇列BloC
- JAVA中常見的阻塞佇列詳解Java佇列
- 從0到1實現自己的阻塞佇列(上)佇列
- 什麼是阻塞佇列?如何使用阻塞佇列來實現生產者-消費者模型?佇列模型
- 快速理解Go陣列和切片的內部實現原理Go陣列
- Java併發——阻塞佇列集(下)Java佇列
- Java併發——阻塞佇列集(上)Java佇列
- Java 中佇列同步器 AQS(AbstractQueuedSynchronizer)實現原理Java佇列AQS
- AQS原始碼深入分析之條件佇列-你知道Java中的阻塞佇列是如何實現的嗎?AQS原始碼佇列Java
- JAVA併發之阻塞佇列淺析Java佇列
- Java併發程式設計:阻塞佇列Java程式設計佇列
- Java併發程式設計——阻塞佇列Java程式設計佇列
- iOS 揭露Block的內部實現原理iOSBloC
- Java中常用七個阻塞佇列的總結Java佇列
- 死磕阻塞佇列佇列
- 【資料結構】佇列(順序佇列、鏈佇列)的JAVA程式碼實現資料結構佇列Java
- 解讀Promise內部實現原理Promise