阻塞队列BlockingQueue

Posted 啊哈咧

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了阻塞队列BlockingQueue相关的知识,希望对你有一定的参考价值。

BlockingQueue最终会有四种状况,抛出异常、返回特殊值、阻塞、超时,下表总结了这些方法:

 

抛出异常

特殊值

阻塞

超时

插入

add(e)

offer(e)

put(e)

offer(e, time, unit)

移除

remove()

poll()

take()

poll(time, unit)

检查

element()

peek()

不可用

不可用

       

 

 

 

 

 

BlockingQueue是个接口,有如下实现类:

       1. ArrayBlockQueue:一个由数组支持的有界阻塞队列。此队列按 FIFO(先进先出)原则对元素进行排序。创建其对象必须明确大小,像数组一样。

       2. LinkedBlockQueue:一个可改变大小的阻塞队列。此队列按 FIFO(先进先出)原则对元素进行排序。创建其对象如果没有明确大小,默认值是Integer.MAX_VALUE。链接队列的吞吐量通常要高于基于数组的队列,但是在大多数并发应用程序中,其可预知的性能要低。 

       3. PriorityBlockingQueue:类似于LinkedBlockingQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数所带的Comparator决定的顺序。

       4. SynchronousQueue:同步队列。同步队列没有任何容量,每个插入必须等待另一个线程移除,反之亦然。

       下面使用ArrayBlockQueue来实现之前实现过的生产者消/费者模式,代码如下:

  1. /** 定义一个盘子类,可以放鸡蛋和取鸡蛋 */  
  2. public class BigPlate {  
  3. /** 装鸡蛋的盘子,大小为5 */  
  4. private BlockingQueue<Object> eggs = new ArrayBlockingQueue<Object>(5);  
  5. /** 放鸡蛋 */  
  6. public void putEgg(Object egg) {  
  7. try {  
  8. eggs.put(egg);// 向盘子末尾放一个鸡蛋,如果盘子满了,当前线程阻塞  
  9. catch (InterruptedException e) {  
  10. e.printStackTrace();  
  11. }  
  12. // 下面输出有时不准确,因为与put操作不是一个原子操作  
  13. System.out.println("放入鸡蛋");  
  14. }  
  15. /** 取鸡蛋 */  
  16. public Object getEgg() {  
  17. Object egg = null;  
  18. try {  
  19. egg = eggs.take();// 从盘子开始取一个鸡蛋,如果盘子空了,当前线程阻塞  
  20. catch (InterruptedException e) {  
  21. e.printStackTrace();  
  22. }  
  23. // 下面输出有时不准确,因为与take操作不是一个原子操作  
  24. System.out.println("拿到鸡蛋");  
  25. return egg;  
  26. }  
  27. /** 放鸡蛋线程 */  
  28. static class AddThread extends Thread {  
  29. private BigPlate plate;  
  30. private Object egg = new Object();  
  31. public AddThread(BigPlate plate) {  
  32. this.plate = plate;  
  33. }  
  34. public void run() {  
  35. plate.putEgg(egg);  
  36. }  
  37. }  
  38. /** 取鸡蛋线程 */  
  39. static class GetThread extends Thread {  
  40. private BigPlate plate;  
  41. public GetThread(BigPlate plate) {  
  42. this.plate = plate;  
  43. }  
  44. public void run() {  
  45. plate.getEgg();  
  46. }  
  47. }  
  48. public static void main(String[] args) {  
  49. BigPlate plate = new BigPlate();  
  50. // 先启动10个放鸡蛋线程  
  51. for(int i = 0; i < 10; i++) {  
  52. new Thread(new AddThread(plate)).start();  
  53. }  
  54. // 再启动10个取鸡蛋线程  
  55. for(int i = 0; i < 10; i++) {  
  56. new Thread(new GetThread(plate)).start();  
  57. }  
  58. }  
  59. }  

以上是关于阻塞队列BlockingQueue的主要内容,如果未能解决你的问题,请参考以下文章

阻塞队列--概述

并发阻塞队列和非阻塞队列详解

什么是阻塞队列?如何使用阻塞队列来实现生产者-消费者模型?

阻塞队列和线程池原理

阻塞队列BlockingQueue

阻塞队列与非阻塞队列