Pratice Of Concurrency(一: BlockingQueue )
Java java.util.currency包中的BlockingQueue接口意味著線程可以在一個(gè)隊(duì)列中添加和提取對(duì)象.在接下來的段落中,我們將學(xué)習(xí)如何使用BlockingQueue接口.
BlockingQueue的使用
BlockingQueue典型應(yīng)用是用于一個(gè)線程生產(chǎn)對(duì)象,另一個(gè)線程消費(fèi)對(duì)象.
下面是一個(gè)原理描述圖:
一個(gè)阻塞隊(duì)列伴隨著一個(gè)線程往隊(duì)列中添加對(duì)象,另一個(gè)線程從隊(duì)列中提取對(duì)象.
生產(chǎn)線程負(fù)責(zé)生產(chǎn)新對(duì)象并發(fā)它添加進(jìn)隊(duì)列中,直到達(dá)到隊(duì)列所能容納的邊界值為止.即達(dá)到容量限制.如果隊(duì)列達(dá)到容量限制,則生產(chǎn)線程在插入新對(duì)象時(shí)將會(huì)發(fā)生阻塞.直到有一個(gè)消費(fèi)線程從隊(duì)列中取走一個(gè)對(duì)象為止.
消費(fèi)線程負(fù)責(zé)從阻塞隊(duì)列中取出對(duì)象并處理它們.如果消費(fèi)線程嘗試從空隊(duì)列中取出空隊(duì)列,那么消費(fèi)線程將會(huì)阻塞直到生產(chǎn)線程往隊(duì)列中放入一個(gè)對(duì)象為止.
BlockingQueue方法
一個(gè)阻塞隊(duì)列包含四種截然不同的方法集,用于完成在隊(duì)列中插入,移除和檢查元素.每種集合的不同之處在于操作請(qǐng)求不能被立即執(zhí)行時(shí)的不同行為.下面是這些方法的列表:
| Insert | add(o) | offer(o) | put(o) | offer(o, timeout, time unit) |
| Remove | remove(o) | poll() | take() | poll(timeout, timeunit) |
| Examine | element() | peek() |
四種不同的行為結(jié)合如下:
不能插入null到BlockingQueue中.如果你這么做了,BlockingQueue將拋出一個(gè)NullPointerException.
當(dāng)然我們也能夠訪問BlockingQueue的所有元素, 不只是隊(duì)頭和隊(duì)尾. 例如, 你需要出隊(duì)一個(gè)對(duì)象用于執(zhí)行,但你的應(yīng)用決定取消它.那么你仍然可以使用類似remove(o)方法來移除隊(duì)列中指定的對(duì)象.然而這不是很高效,所以你不應(yīng)該使用這類方法, 除非你真的需要這么做.
BlockingQueue的多種實(shí)現(xiàn)
BlockingQueue只是一個(gè)接口, 所以你需要使用它眾多實(shí)現(xiàn)的其中一種來使用它.java.util.concurrency包中有如下幾種BlockingQueue的接口實(shí)現(xiàn)(在Java6中):
- ArrayBlockingQueue
- DelayQueue
- LinkedBlockingQueue
- PriorityBlockingQueue
- SynchronousQueue
Java BlockingQueue實(shí)例
下面是一個(gè)Java BlockingQueue的實(shí)例. 實(shí)例中使用BlockingQueue接口的實(shí)現(xiàn)類,ArrayBlockingQueue.
首先,BlockingQueueExample類中分別啟動(dòng)一個(gè)生產(chǎn)和消費(fèi)線程.生產(chǎn)線程負(fù)責(zé)插入字符串到共享BlockingQueue中,而消費(fèi)線程則負(fù)責(zé)取走它們.
public class ArrayBlockingQueueExample {public static void main(String[] args) {ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(1024);Producer producer = new Producer(queue);Consumer consumer = new Consumer(queue);new Thread(producer).start();new Thread(consumer).start();try {Thread.sleep(4000);} catch (InterruptedException e) {e.printStackTrace();}} } 復(fù)制代碼下面是Producer類.注意我們每調(diào)用一次put()就會(huì)讓線程睡眠一秒.這會(huì)導(dǎo)致消費(fèi)線程在隊(duì)列中等待對(duì)象時(shí)發(fā)生阻塞.
public class Producer implements Runnable {private ArrayBlockingQueue<String> queue;public Producer(ArrayBlockingQueue<String> queue) {this.queue = queue;}public void run() {try {queue.put("1");Thread.sleep(1000);queue.put("2");Thread.sleep(1000);queue.put("3");Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}} } 復(fù)制代碼下面是Consumer類.它只是負(fù)責(zé)從隊(duì)列中取出字符串并通過System.out打印出來.
package org.menfre;import java.util.concurrent.ArrayBlockingQueue;public class Consumer implements Runnable {private ArrayBlockingQueue<String> queue;public Consumer(ArrayBlockingQueue<String> 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();}} } 復(fù)制代碼該系列博文為筆者復(fù)習(xí)基礎(chǔ)所著譯文或理解后的產(chǎn)物,復(fù)習(xí)原文來自Jakob Jenkov所著Java.util.concurrent
Next: ArrayBlockingQueue
轉(zhuǎn)載于:https://juejin.im/post/5cf548aef265da1bb2771b0d
總結(jié)
以上是生活随笔為你收集整理的Pratice Of Concurrency(一: BlockingQueue )的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 质感设计 android,扣丁学堂And
- 下一篇: 数据仓库建设Best Pratice学习