Java SynchronusQueue 使用
本章主要介紹 SynchronusQueue 的使用
特點:
1、容量爲 0
2、實際上該隊列不是爲了存放元素的,而是爲了給另外的線程下達任務,傳遞信息使用的
代碼示例:
package com.jacky.test;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
public class SynchronusQueueTest {
public static void main(String[] args) throws Exception {
//必須先有一個線程等着消費此隊列的內容
BlockingQueue<String> strs = new SynchronousQueue<>();//容量爲0
new Thread(() -> {
try {
System.out.println(strs.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
System.out.println("before size = "+strs.size());
strs.put("aaa");//阻塞等待消費者消費
// strs.put("bbb");
// strs.add("ccc");//會拋異常,提示隊列已滿
System.out.println("after size = "+strs.size());
}
}
代碼解讀:
主線程存入一個元素,子線程取出隊列中的元素
如果子線程註釋掉,則主線程會一直阻塞在 put 那行代碼,
如果用 add 方式添加,必須開啓子線程,否則會拋出異常,提示隊列已滿。
上面的代碼看不出信息傳遞的效果,下面結合源碼就能看出不同於其他隊列了
運行結果:
源碼解讀:
/**
* Retrieves and removes the head of this queue, waiting if necessary
* for another thread to insert it.
*
* @return the head of this queue
* @throws InterruptedException {@inheritDoc}
*/
public E take() throws InterruptedException {
E e = transferer.transfer(null, false, 0);
if (e != null)
return e;
Thread.interrupted();
throw new InterruptedException();
}
/**
* Adds the specified element to this queue, waiting if necessary for
* another thread to receive it.
*
* @throws InterruptedException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
if (transferer.transfer(e, false, 0) == null) {
Thread.interrupted();
throw new InterruptedException();
}
}
以上源碼可以看出,不管是存還是取,都是通過 transfer 的方式進行消息傳遞,不同於之前文章介紹的隊列實現。
傳遞實現有兩種,具體可以自行研讀源碼細節
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/PbuODaPRJycd_PCta5COEQ