java並發編程工具類JUC之ArrayBlockingQueue

Java BlockingQueue接口java.util.concurrent.BlockingQueue表示一個可以存取元素,並且線程安全的隊列。換句話說,當多線程同時從 JavaBlockingQueue中插入元素、獲取元素的時候,不會導致任何並發問題(元素被插入多次、處理多次等問題)。

從java BlockingQueue可以引申出一個概念:阻塞隊列,是指隊列本身可以阻塞線程向隊列裡面插入元素,或者阻塞線程從隊列裡面獲取元素。比如:當一個線程嘗試去從一個空隊列裡面獲取元素的時候,這個線程將被阻塞直到隊列內元素數量不再為空。當然,線程是否會被阻塞取決於你調用什麼方法從BlockingQueue獲取元素,有的方法會阻塞線程,有的方法會拋出異常等等,下文我們會詳細介紹。

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的時候就已經進行過說明。

以上就是java並發編程工具類JUC之ArrayBlockingQueue的詳細內容,更多關於java並發編程工具類ArrayBlockingQueue的資料請關註WalkonNet其它相關文章!

推薦閱讀: