LinkedBlockingQueue實現的生產者和消費者模型 LinkedBlockingQueue

首先 LinkedBlockingQueue 是線程安全的阻塞隊列,LinkedBlockingQueue實現的生產者和消費者模型

阻塞隊列與我們平常接觸的普通隊列(LinkedList或ArrayList等)的最大不同點,在於阻塞隊列支出阻塞添加和阻塞刪除方法。

阻塞添加:所謂的阻塞添加是指當阻塞隊列元素已滿時,隊列會阻塞加入元素的線程,直隊列元素不滿時才重新喚醒線程執行元素加入操作。

阻塞刪除:阻塞刪除是指在隊列元素爲空時,刪除隊列元素的線程將被阻塞,直到隊列不爲空再執行刪除操作(一般都會返回被刪除的元素)

BlockingQueue的核心方法:
放入數據:
  offer(anObject):表示如果可能的話,將anObject加到BlockingQueue裏,即如果BlockingQueue可以容納,則返回true,否則返回false.(本方法不阻塞當前執行方法的線程)
  offer(E o, long timeout, TimeUnit unit):可以設定等待的時間,如果在指定的時間內,還不能往隊列中加入BlockingQueue,則返回失敗。
  put(anObject):把anObject加到BlockingQueue裏,如果BlockQueue沒有空間,則調用此方法的線程被阻斷直到BlockingQueue裏面有空間再繼續.
獲取數據:
  poll(time):取走BlockingQueue裏排在首位的對象,若不能立即取出,則可以等time參數規定的時間,取不到時返回null;
  poll(long timeout, TimeUnit unit):從BlockingQueue取出一個隊首的對象,如果在指定時間內,隊列一旦有數據可取,則立即返回隊列中的數據。否則知道時間超時還沒有數據可取,返回失敗。
  take():取走BlockingQueue裏排在首位的對象,若BlockingQueue爲空,阻斷進入等待狀態直到BlockingQueue有新的數據被加入;
  drainTo():一次性從BlockingQueue獲取所有可用的數據對象(還可以指定獲取數據的個數),通過該方法,可以提升獲取數據效率;不需要多次分批加鎖或釋放鎖。

如果不指定隊列的容量大小,也就是使用默認的Integer.MAX_VALUE,如果存在添加速度大於刪除速度時候,有可能會內存溢出(OOM)

寫法一:

生產者 Producer.java

package com.vipsoft.web.app;

import java.util.concurrent.LinkedBlockingQueue;

public class Producer extends Thread {
    //1、通過構造函數傳入阻塞隊列
    public static LinkedBlockingQueue<String> queue; 
    
    public Producer(LinkedBlockingQueue<String> queue) {
        this.queue = queue;
    }

    public void run() {
        int i = 0;
        while (true) {
            i++;
            try {
                String msg = "P" + i;
                queue.put(msg);
                System.out.println("我生產了 => " + msg + " 隊列數量 " + queue.size());
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("Producer queue.size => " + queue.size());
                e.printStackTrace();
            } 
        }
    }
}

消費者 Consumer.java

package com.vipsoft.web.app;

import java.util.concurrent.LinkedBlockingQueue;

public class Consumer extends Thread {
    public static LinkedBlockingQueue<String> queue;

    public Consumer(LinkedBlockingQueue<String> queue) {
        this.queue = queue;
    }

    public void run() { 
        while (true) {
            try {
                System.out.println("我消費了 => " + queue.take() + " 隊列數量 " + queue.size());
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                System.out.println("Consumer queue.size() => " + queue.size());
                e.printStackTrace();
            }

        }
    }
}

主程序

package com.vipsoft.web.app;
 
import java.util.concurrent.LinkedBlockingQueue;

public class LinkedBlockingQueueTest {

    public static void main(String[] args) {

        //1、創建一個BlockingQueue
        int MAX_NUM = 10;  //實際使用也需要指定大小,防止OOM
        LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>(MAX_NUM);


        //2、創建一個生產者,一個消費者
        Producer producer = new Producer(queue);
        Consumer consumer = new Consumer(queue);

        //3、開啓兩個線程
        producer.start();
        consumer.start();

    }
}

寫法二:

package com.vipsoft.web.app;
 
import java.util.concurrent.LinkedBlockingDeque;

public class LinkedBlockingQueueTest {

    public static void main(String[] args) {

        final LinkedBlockingDeque<String> queue = new LinkedBlockingDeque<>(10); //實際使用也需要指定大小,防止OOM

        Runnable producerRunnable = new Runnable() {
            public void run() {
                int i = 0;
                while (true) {
                    i++;
                    try {
                        String msg = "P" + i;
                        queue.put(msg);
                        System.out.println("我生產了 => " + msg + " 隊列數量 " + queue.size());
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        System.out.println("Producer queue.size => " + queue.size());
                        e.printStackTrace();
                    }
                }
            }
        };

        Runnable customerRunnable = new Runnable() {
            public void run() {
                while (true) {
                    try {
                        System.out.println("我消費了 => " + queue.take() + " 隊列數量 " + queue.size());
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        System.out.println("Consumer queue.size() => " + queue.size());
                        e.printStackTrace();
                    }
                }
            }
        };

        Thread thread1 = new Thread(producerRunnable);
        thread1.start();

        Thread thread2 = new Thread(customerRunnable);
        thread2.start();
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章