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