JUC阻塞佇列BlockingQueue

2021-10-09 21:42:00 字數 2342 閱讀 8076

前言:最近面試和手動建立執行緒池時都用到了阻塞佇列,不由得產生好奇,**一下原理

參考:目錄

第一章 基礎使用

第二章 實現原理

2.1 arrayblockingqueue

2.2 linkedblockingqueue

第三章 執行緒池中所之用的阻塞佇列

juc中實現乙個阻塞佇列一般都會實現blockingqueue介面,主要方法說明

網上說的主流的阻塞佇列實現有兩種,分別是arrayblockingqueue和linkedblockingqueue

基於陣列的阻塞佇列實現,其內部維護乙個定長的陣列,用於儲存佇列元素。執行緒阻塞的實現是通過reentrantlock來完成的,資料的插入與取出共用同乙個鎖,因此arrayblockingqueue並不能實現生產、消費同時進行。而且在建立arrayblockingqueue時,我們還可以控制物件的內部鎖是否採用公平鎖,預設採用非公平鎖。

可以看到只new了乙個reentrantlock,所以插入與取出公用乙個鎖。

public arrayblockingqueue(int capacity, boolean fair)
基於單向鍊錶的阻塞佇列實現,在初始化linkedblockingqueue的時候可以指定對立的大小,也可以不指定,預設類似乙個無限大小的容量(integer.max_value),不指佇列容量大小也是會有風險的,一旦資料生產速度大於消費速度,系統記憶體將有可能被消耗殆盡,因此要謹慎操作。另外linkedblockingqueue中用於阻塞生產者、消費者的鎖是兩個(鎖分離),因此生產與消費是可以同時進行的。

可以看到用了兩個reentrantlock鎖

private final reentrantlock takelock = new reentrantlock();

/** wait queue for waiting takes */

private final condition notempty = takelock.newcondition();

/** lock held by put, offer, etc */

private final reentrantlock putlock = new reentrantlock();

在建立執行緒池時我發現會傳入linkedbockingqueue阻塞佇列。

public static executorservice newfixedthreadpool(int nthreads)
然後我實驗了一下,發現當向執行緒池插入過量執行緒時並不會阻塞插入執行緒的佇列,具體**如下:

所以說加入額外的執行緒並沒有阻塞當前執行緒

class mytest implements runnable

@override

public void run() catch (interruptedexception e)

}}public class threadpooltest

threadpool.shutdown();

system.out.println("結束");}}

輸出:

heihei

當前執行到0

heihei

當前執行到1

heihei

heihei

當前執行到2

heihei

heihei

heihei

heihei

heihei

heihei

結束當前執行到3

當前執行到4

當前執行到5

當前執行到6

當前執行到7

當前執行到8

當前執行到9

process finished with exit code 0

鑑於上面的情況我看了一下原始碼,我發現呼叫的是阻塞佇列的offer的方法向阻塞佇列中加入執行緒的,根據3.1中列出的方法,所以不會阻塞當前執行緒,如果是put方法就會阻塞了。

public void execute(runnable command) 

//可以看到是offer

if (isrunning(c) && workqueue.offer(command))

else if (!addworker(command, false))

reject(command);

}

JUC 阻塞佇列

什麼是阻塞佇列 阻塞佇列常用於生產者和消費者場景,生產者是向佇列裡新增元素的執行緒,消費者是從佇列裡獲取元素的執行緒。阻塞佇列就是生產者用來存放元素 消費者用來獲取元素的容器 為什麼要使用阻塞佇列 就是適用在不得不阻塞的場景如上面所說生產者 和 消費者場景中 要是佇列中為空 消費者不得不進行阻塞 佇...

juc 阻塞佇列BlockingQueue

阻塞佇列blockingqueue的方法分類 方法型別 丟擲異常 特殊值阻塞 超時插入 add e offer e put e offer e,time,unit 移除remove poll take poll time,unit 檢查element peek 不可用不可用 丟擲異常 當阻塞佇列滿時...

JUC學習 阻塞佇列

在這篇部落格中我們接觸的佇列都是非阻塞佇列,比如priorityqueue linkedlist linkedlist是雙向鍊錶,它實現了dequeue介面 阻塞佇列常用於執行緒池和生產者消費者的問題中 使用非阻塞佇列的時候有乙個很大問題就是 它不會對當前執行緒產生阻塞,那麼在面對類似消費者 生產者...