java併發程式設計工具類JUC第二篇:ArrayBlockingQueue

字母哥部落格發表於2021-05-31

ArrayBlockingQueueBlockingQueue介面的實現類,它是有界的阻塞佇列,內部使用陣列儲存佇列元素。這裡的“有界”是指儲存容量存在上限,不能無限儲存元素。在同一時間記憶體儲容量存在著一個上限值,這個上限制在初始例項化的時候指定,之後便不能修改了。

ArrayBlockingQueue內部採用FIFO (First In, First Out)先進先出的方法實現佇列資料的存取,隊首的元素是在佇列中儲存時間最長的元素物件,隊尾的元素是在佇列中儲存時間最短的元素物件。

下面的程式碼說明如何初始化一個ArrayBlockingQueue,並向其中新增一個物件:

BlockingQueue queue = new ArrayBlockingQueue(1024);
queue.put("1");   //向佇列中新增元素
Object object = queue.take();   //從佇列中取出元素

BlockingQueue可以通過泛型來限定佇列中儲存資料的型別,下面的程式碼以String為泛型,表示該佇列只能儲存String型別。

BlockingQueue<String> queue = new ArrayBlockingQueue<String>(1024);
queue.put("1");
String string = queue.take();

實現一個生產消費的例項

在前面的文章中我們曾經講過:BlockingQueue經常被用於生產消費的緩衝佇列。下面我們就使用ArrayBlockingQueue來真正的實現一個生產消費的例子。

BlockingQueueExample開啟兩個獨立執行緒,一個是Producer生產者執行緒,負責向佇列中新增資料;另一個是Consumer消費者執行緒,負責從佇列中取出資料進行處理。

public class BlockingQueueExample {

    public static void main(String[] args) throws Exception {
        //使用ArrayBlockingQueue初始化一個BlockingQueue,指定容量的上限為1024
        BlockingQueue queue = new ArrayBlockingQueue(1024);
        
        Producer producer = new Producer(queue);  //生產者
        Consumer consumer = new Consumer(queue);  //消費者

        new Thread(producer).start();  //開啟生產者執行緒
        new Thread(consumer).start();  //開啟消費者執行緒

        Thread.sleep(4000);
    }
}

Producer為生產者,每隔10秒鐘使用put()方法向佇列中放入一個物件,放入三次。在這10秒的間隔內,佇列資料被消費者取走之後將導致消費者執行緒阻塞。

public class Producer implements Runnable{

    protected BlockingQueue queue = null;

    public Producer(BlockingQueue queue) {
        this.queue = queue;
    }

    public void run() {
        try {
            queue.put("1");
            Thread.sleep(10000);
            queue.put("2");
            Thread.sleep(10000);
            queue.put("3");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

下面的程式碼是消費者類Consumer,它從佇列中獲取待處理的元素物件,並呼叫System.out將其列印出來。

public class Consumer implements Runnable{

    protected BlockingQueue queue = null;

    public Consumer(BlockingQueue queue) {
        this.queue = queue;
    }

    public void run() {
        try {
            System.out.println(queue.take());
            System.out.println(queue.take());
            System.out.println(queue.take());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

上面的程式碼列印結果是每隔10秒列印一次,因為其中take()方法在佇列內沒有元素可以取到的時候,會阻塞當前的消費者執行緒,讓其處於等待狀態,這個方法我們在上一節介紹BlockingQueue的時候就已經進行過說明。

歡迎關注我的部落格,裡面有很多精品合集

  • 本文轉載註明出處(必須帶連線,不能只轉文字):字母哥部落格

覺得對您有幫助的話,幫我點贊、分享!您的支援是我不竭的創作動力! 。另外,筆者最近一段時間輸出瞭如下的精品內容,期待您的關注。

相關文章