JUC并发编程学习笔记(九)阻塞队列
生活随笔
收集整理的這篇文章主要介紹了
JUC并发编程学习笔记(九)阻塞队列
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
阻塞隊列
阻塞
隊列
隊列的特性:FIFO(fist inpupt fist output)先進先出
不得不阻塞的情況
什么情況下會使用阻塞隊列:多線程并發處理、線程池
學會使用隊列
添加、移除
四組API
| 方式 | 拋出異常 | 不拋出異常,有返回值 | 阻塞等待 | 超時等待 |
|---|---|---|---|---|
| 添加 | add | offer | put | offer(E e, long timeout, TimeUnit unit) |
| 移除 | remove | poll | take | poll(long timeout, TimeUnit unit) |
| 檢測隊首元素 | element | peek |
1、拋出異常
public static void test01(){
//隊列是有大小的,創建時要明確該隊列最大能有幾個元素
BlockingQueue queue = new ArrayBlockingQueue<>(3);
//當你添加的元素超出隊列規定的最大元素量時,拋出異常java.lang.IllegalStateException: Queue full
System.out.println(queue.add("A"));
System.out.println(queue.add("B"));
System.out.println(queue.add("C"));
//當你移除的元素超出隊列中含有的元素量時,拋出異常java.util.NoSuchElementException
System.out.println(queue.element());
System.out.println(queue.remove());
System.out.println(queue.element());
System.out.println(queue.remove());
System.out.println(queue.element());
System.out.println(queue.remove());
System.out.println(queue.add("D"));
}
2、不拋出異常
public static void test02(){
//隊列是有大小的,創建時要明確該隊列最大能有幾個元素
BlockingQueue queue = new ArrayBlockingQueue<>(3);
//當你添加的元素超出隊列規定的最大元素量時,不拋出異常,通過返回的boolean值為false來表明
System.out.println(queue.offer("A"));
System.out.println(queue.offer("B"));
System.out.println(queue.offer("C"));
//當你移除的元素超出隊列中含有的元素量時,不拋出異常,返回null來提示隊列已經沒有元素可以彈出了
System.out.println(queue.peek());
System.out.println(queue.poll());
System.out.println(queue.peek());
System.out.println(queue.poll());
System.out.println(queue.peek());
System.out.println(queue.poll());
System.out.println(queue.offer("D"));
}
3、阻塞等待
public static void test03() throws InterruptedException {
//隊列是有大小的,創建時要明確該隊列最大能有幾個元素
BlockingQueue queue = new ArrayBlockingQueue<>(3);
queue.put("a");
queue.put("b");
queue.put("c");
//當隊列被元素占滿后再進行添加,會一直阻塞等待,知道該元素加入隊列
// queue.put("c");
System.out.println(queue.take());
System.out.println(queue.take());
System.out.println(queue.take());
//當隊列中沒有元素時還去取,也會一直阻塞等待
// System.out.println(queue.take());
}
4、超時等待
public static void test04() throws Exception{
//隊列是有大小的,創建時要明確該隊列最大能有幾個元素
BlockingQueue queue = new ArrayBlockingQueue<>(3);
System.out.println(queue.offer("a"));
System.out.println(queue.offer("b"));
System.out.println(queue.offer("c"));
//當隊列被占滿時,設置超時等待,超過兩秒就不等了,進不去就不進了
System.out.println(queue.offer("d", 2, TimeUnit.SECONDS));
System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());
//當隊列元素為空時,設置超時等待,超過兩秒就不等了,拿不到就不拿了
System.out.println(queue.poll(2, TimeUnit.SECONDS));
}
SynchronousQueue
同步隊列:同步隊列每次插入操作都必須等待另一個線程執行相應的刪除操作,反之亦然。同步隊列沒有容量,也就意味著只有當一個元素彈出后才能再進入一個元素,只能同時有一個元素。
存取:put、take
package org.example.qu;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
public class SynchronousQueueDemo {
public static void main(String[] args) {
SynchronousQueue<String> synchroQueue = new SynchronousQueue<String>();
new Thread(() -> {
try {
//直接在隊列中存入三個元素
System.out.println(Thread.currentThread().getName() + ": put 1");
synchroQueue.put("1");
System.out.println(Thread.currentThread().getName() + ": put 2");
synchroQueue.put("2");
System.out.println(Thread.currentThread().getName() + ": put 3");
synchroQueue.put("3");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}, "T1").start();
new Thread(() -> {
try {
//每次取之間延遲三秒
TimeUnit.SECONDS.sleep(3);
System.out.println(synchroQueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(synchroQueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(synchroQueue.take());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}, "T2").start();
}
}
我們通過結果發現,將要存入的元素會等待已經被存入的元素取出后才會存入,延遲三秒取出時,將要存入的元素也在等待三秒取出后再存入,這就是所謂的同步隊列每次插入操作都必須等待另一個線程執行相應的刪除操作,反之亦然。
同步隊列和其它BlockingQueue不一樣,他不存儲元素,你put了一個值必須take取出,否則不能再put進去元素。
總結
以上是生活随笔為你收集整理的JUC并发编程学习笔记(九)阻塞队列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .NET起步
- 下一篇: 手记系列之七 ----- 分享Linux