Java阻塞隊(duì)列BlockingQueue基礎(chǔ)與使用
什么是阻塞隊(duì)列
阻塞隊(duì)列本質(zhì)上還是一種隊(duì)列,遵循先進(jìn)先出,后進(jìn)后出的原則,在此基礎(chǔ)上,如果出隊(duì)時(shí)阻塞隊(duì)列為空,則會(huì)使當(dāng)前線程陷入阻塞,直到入隊(duì)新元素時(shí)通知線程繼續(xù)執(zhí)行,如果入隊(duì)時(shí)阻塞隊(duì)列為滿,則會(huì)使當(dāng)前線程陷入阻塞,直到出隊(duì)舊元素時(shí)才通知線程進(jìn)行執(zhí)行。
阻塞隊(duì)列的特點(diǎn)

BlockingQueue不是新的東西

學(xué)會(huì)使用隊(duì)列
阻塞隊(duì)列四組API
| 方式 | 拋出異常 | 有返回值,不拋出異常 | 阻塞 等待 | 超時(shí)等待 |
|---|---|---|---|---|
| 添加 | add(E e) | offer(E e) | put() | offer(E e,Time,TimeUnit) |
| 移除 | remove() | poll() | take() | poll(Time,TimeUnit) |
| 檢測(cè)隊(duì)首元素 | element() | peek | 無(wú) | 無(wú) |
- 拋出異常是指當(dāng)隊(duì)列滿時(shí),再次插入會(huì)拋出異常(如果隊(duì)列未滿,插入返回值未true);
- 返回布爾是指當(dāng)隊(duì)列滿時(shí),再次插入會(huì)返回false;
- 阻塞是指當(dāng)隊(duì)列滿時(shí),再次插入會(huì)被阻塞,直到隊(duì)列取出一個(gè)元素,才能插入。
- 超時(shí)是指當(dāng)一個(gè)時(shí)限過(guò)后,才會(huì)插入或者取出。
拋出異常
/**
* 拋出異常
*/
public static void test1(){
// 隊(duì)列的大小
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
System.out.println(blockingQueue.add("a"));
System.out.println(blockingQueue.add("b"));
System.out.println(blockingQueue.add("c"));
// IllegalStateException: Queue full 拋出異常!
// System.out.println(blockingQueue.add("d"));
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
// java.util.NoSuchElementException 拋出異常!
// System.out.println(blockingQueue.remove());
}
有返回值,沒有異
/**
* 有返回值,沒有異常
*/
public static void test2(){
// 隊(duì)列的大小
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
System.out.println(blockingQueue.offer("a"));
System.out.println(blockingQueue.offer("b"));
System.out.println(blockingQueue.offer("c"));
// System.out.println(blockingQueue.offer("d")); // false 不拋出異常!
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll()); // null 不拋出異常!
}
等待,阻塞(一直阻塞)
/**
* 等待,阻塞(一直阻塞)
*/
public static void test3() throws InterruptedException {
// 隊(duì)列的大小
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
// 一直阻塞
blockingQueue.put("a");
blockingQueue.put("b");
blockingQueue.put("c");
// blockingQueue.put("d"); // 隊(duì)列沒有位置了,一直阻塞
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take())
}
等待,阻塞(等待超時(shí)
/**
* 等待,阻塞(等待超時(shí))
*/
public static void test4() throws InterruptedException {
// 隊(duì)列的大小
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
blockingQueue.offer("a");
blockingQueue.offer("b");
blockingQueue.offer("c");
// blockingQueue.offer("d",2,TimeUnit.SECONDS); // 等待超過(guò)2秒就退出
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
blockingQueue.poll(2,TimeUnit.SECONDS);
}
SynchronousQueue 同步隊(duì)列
和其他的BlockingQueue 不一樣, SynchronousQueue 不存儲(chǔ)元素
put了一個(gè)元素,必須從里面先take取出來(lái),否則不能在put進(jìn)去值!
public class SynchronousQueueDemo {
public static void main(String[] args) {
BlockingQueue<String> blockingQueue = new SynchronousQueue<>(); // 同步隊(duì)
// new Thread(()->{
try {
System.out.println(Thread.currentThread().getName()+" put 1");
blockingQueue.put("1");
System.out.println(Thread.currentThread().getName()+" put 2");
blockingQueue.put("2");
System.out.println(Thread.currentThread().getName()+" put 3");
blockingQueue.put("3");
} catch (InterruptedException e) {
e.printStackTrace();
}
},"T1").start();
new Thread(()->{
try {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()+"=>"+blockingQueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()+"=>"+blockingQueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()+"=>"+blockingQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
},"T2").start();
}
}
到此這篇關(guān)于Java阻塞隊(duì)列BlockingQueue基礎(chǔ)與使用的文章就介紹到這了,更多相關(guān)Java BlockingQueue內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java之Swagger配置掃描接口以及開關(guān)案例講解
這篇文章主要介紹了Java之Swagger配置掃描接口以及開關(guān)案例講解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
springboot實(shí)現(xiàn)異步調(diào)用@Async的示例
這篇文章主要介紹了springboot實(shí)現(xiàn)異步調(diào)用@Async的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
java JVM原理與常識(shí)知識(shí)點(diǎn)
在本文中小編給大家分享的是關(guān)于java的JVM原理和java常識(shí),有興趣的朋友們可以學(xué)習(xí)下2018-12-12
Spring Data JPA實(shí)現(xiàn)分頁(yè)P(yáng)ageable的實(shí)例代碼
本篇文章主要介紹了Spring Data JPA實(shí)現(xiàn)分頁(yè)P(yáng)ageable的實(shí)例代碼,具有一定的參考價(jià)值,有興趣的可以了解一下2017-07-07
淺談Java如何實(shí)現(xiàn)一個(gè)基于LRU時(shí)間復(fù)雜度為O(1)的緩存
這篇文章主要介紹了淺談Java如何實(shí)現(xiàn)一個(gè)基于LRU時(shí)間復(fù)雜度為O(1)的緩存,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08
springboot Controller直接返回String類型帶來(lái)的亂碼問題及解決
文章介紹了在Spring Boot中,當(dāng)Controller直接返回String類型時(shí)可能出現(xiàn)的亂碼問題,并提供了解決辦法,通過(guò)在`application.yaml`中設(shè)置請(qǐng)求和響應(yīng)的編碼格式,并在自定義配置類中進(jìn)行配置,可以有效解決這一問題2024-11-11
Intellij IDEA 2019 最新亂碼問題及解決必殺技(必看篇)
大家在使用Intellij IDEA 的時(shí)候會(huì)經(jīng)常遇到各種亂碼問題,今天小編給大家分享一些關(guān)于Intellij IDEA 2019 最新亂碼問題及解決必殺技,感興趣的朋友跟隨小編一起看看吧2020-04-04

