java並發編程(二十四)----(JUC集合)ArrayBlockingQueue和LinkedBlockingQueue介紹__編程

來源:互聯網
上載者:User

這一節我們來瞭解阻塞隊列(BlockingQueue),BlockingQueue介面定義了一種阻塞的FIFO queue,每一個BlockingQueue都有一個容量,當容量滿時往BlockingQueue中添加資料時會造成阻塞,當容量為空白時取元素操作會阻塞。首先我們來看ArrayBlockingQueue和LinkedBlockingQueue. ArrayBlockingQueue

ArrayBlockingQueue是一個用數組實現的有界阻塞隊列。此隊列按照先進先出(FIFO)的原則對元素進行排序。預設情況下不保證訪問者公平的訪問隊列,所謂公平訪問隊列是指阻塞的所有生產者線程或消費者線程,當隊列可用時,可以按照阻塞的先後順序訪問隊列,即先阻塞的生產者線程,可以先往隊列裡插入元素,先阻塞的消費者線程,可以先從隊列裡擷取元素。通常情況下為了保證公平性會降低輸送量。

我們看他的建構函式實現:

//預設是非公平的,初始指定隊列容量public ArrayBlockingQueue(int capacity) {       this(capacity, false);   }//該構造方法可以設定隊列的公平性。當然如果為公平的,則對效能會產生影響//訪問者的公平性是使用可重新進入鎖實現的public ArrayBlockingQueue(int capacity, boolean fair) {       if (capacity <= 0)           throw new IllegalArgumentException();       this.items = new Object[capacity];       lock = new ReentrantLock(fair);       notEmpty = lock.newCondition();       notFull =  lock.newCondition();   }

使用很簡單我們直接看一個執行個體:

public class ProducerConsumerTest {   public static void main(String[] args) {        final BlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<Integer>(3);        ExecutorService service = Executors.newFixedThreadPool(10);        for(int i = 0;i<4;i++){            service.execute(new ProducerAndConsumer(blockingQueue));        }    }}class ProducerAndConsumer implements Runnable{    private boolean flag = false;    private Integer j = 1;    private Lock lock = new ReentrantLock();    Condition pro_con = lock.newCondition();    Condition con_con = lock.newCondition();    private BlockingQueue<Integer> blockingQueue;    public ProducerAndConsumer(BlockingQueue<Integer> blockingQueue){        this.blockingQueue= blockingQueue;    }    //生產    public void put(){        try {            lock.lock();            while(flag)                pro_con.await();            System.out.println("正在準備放入資料。。。");            Thread.sleep(new Random().nextInt(10)*100);            Integer value = new Random().nextInt(30);            blockingQueue.put(value);            System.out.println(Thread.currentThread().getName()+"   放入的資料    "+value);            flag = true;            con_con.signal();        } catch (Exception e) {            e.printStackTrace();        }        finally{            lock.unlock();        }    }    public void get(){        try {            lock.lock();            while(!flag)                con_con.await();            System.out.println("正在準備取資料。。。");            Thread.sleep(new Random().nextInt(10)*1000);            System.out.println(Thread.currentThread().getName()+"   取到的資料為"+blockingQueue.take());            flag = false;            pro_con.signal();        } catch (Exception e) {            e.printStackTrace();        }        finally{            lock.unlock();        }    }    @Override    public void run() {        while(true){            if(j==1){                put();            }            else{                get();            }            j=(j+1)%2;        }    }}

輸出為:

正在準備放入資料。。。正在準備放入資料。。。正在準備放入資料。。。正在準備放入資料。。。pool-1-thread-2   放入的資料    13正在準備取資料。。。pool-1-thread-3   放入的資料    4正在準備取資料。。。pool-1-thread-3   取到的資料為13正在準備放入資料。。。pool-1-thread-1   放入的資料    11正在準備取資料。。。pool-1-thread-4   放入的資料    26正在準備取資料。。。pool-1-thread-1   取到的資料為4正在準備放入資料。。。pool-1-thread-2   取到的資料為11正在準備放入資料。。。pool-1-thread-3   放入的資料    18正在準備取資料。。。......
LinkedBlockingQueue

LinkedBlockingQueue是一個用鏈表實現的有界阻塞隊列。此隊列的預設和最大長度為Integer.MAX_VALUE。此隊列按照先進先出的原則對元素進行排序。
先看一下他的建構函式:

public LinkedBlockingQueue() {  this(Integer.MAX_VALUE);  //MAX_VALUE=2147483647 }public LinkedBlockingQueue(int capacity) {     if (capacity <= 0) throw new IllegalArgumentException();     this.capacity = capacity;     last = head = new Node<E>(null); }

我們還是直接開看一個例子:

public class BlockingQueueTest {    /**     * 定義裝蘋果的籃子     */    public static class Basket {        // 籃子,能夠容納3個蘋果        // BlockingQueue<String> basket = new ArrayBlockingQueue<String>(3);        BlockingQueue<String> basket = new LinkedBlockingQueue<String>(3);        // 生產蘋果,放入籃子        public void produce() throws InterruptedException {            // put方法放入一個蘋果,若basket滿了,等到basket有位置            basket.put("An apple");        }        // 消費蘋果,從籃子中取走        public String consume() throws InterruptedException {            // get方法取出一個蘋果,若basket為空白,等到basket有蘋果為止            return basket.take();        }    }    //  測試方法    public static void testBasket() {        // 建立一個裝蘋果的籃子        final Basket basket = new Basket();        // 定義蘋果生產者        class Producer implements Runnable {            public String instance = "";            public Producer(String a) {                instance = a;            }            public void run() {                try {                    while (true) {                        // 生產蘋果                        System.out.println("生產者準備生產蘋果:" + instance);                        basket.produce();                        System.out.println("! 生產者生產蘋果完畢:" + instance);                        // 休眠300ms                        Thread.sleep(300);                    }                } catch (InterruptedException ex) {                }            }        }        // 定義蘋果消費者        class Consumer implements Runnable {            public String instance = "";            public Consumer(String a) {                instance = a;            }            public void run() {                try {                    while (true) {                        // 消費蘋果                        System.out.println("消費者準備消費蘋果:" + instance);                        basket.consume();                        System.out.println("! 消費者消費蘋果完畢:" + instance);                        // 休眠1000ms                        Thread.sleep(1000);                    }                } catch (InterruptedException ex) {                }            }        }        ExecutorService service = Executors.newCachedThreadPool();        Producer producer = new Producer("P1");        Producer producer2 = new Producer("P2");        Consumer consumer = new Consumer("C1");        service.submit(producer);        service.submit(producer2);        service.submit(consumer);        // 程式運行3s後,所有任務停止        try {            Thread.sleep(3000);        } catch (InterruptedException e) {        }        service.shutdownNow();    }    public static void main(String[] args) {        BlockingQueueTest.testBasket();    }}

輸出為:

生產者準備生產蘋果:P1消費者準備消費蘋果:C1! 生產者生產蘋果完畢:P1生產者準備生產蘋果:P2! 消費者消費蘋果完畢:C1! 生產者生產蘋果完畢:P2生產者準備生產蘋果:P2! 生產者生產蘋果完畢:P2生產者準備生產蘋果:P1! 生產者生產蘋果完畢:P1生產者準備生產蘋果:P2生產者準備生產蘋果:P1消費者準備消費蘋果:C1! 消費者消費蘋果完畢:C1! 生產者生產蘋果完畢:P2生產者準備生產蘋果:P2消費者準備消費蘋果:C1! 消費者消費蘋果完畢:C1! 生產者生產蘋果完畢:P1生產者準備生產蘋果:P1消費者準備消費蘋果:C1! 消費者消費蘋果完畢:C1! 生產者生產蘋果完畢:P2Process finished with exit code 0

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.