ArrayBlockingQueue和LinkedBlockingQueue的使用

转载 2018年04月17日 14:25:37

BlockingQueue接口定义了一种阻塞的FIFO queue,每一个BlockingQueue都有一个容量,让容量满时往BlockingQueue中添加数据时会造成阻塞,当容量为空时取元素操作会阻塞。

 

ArrayBlockingQueue是一个由数组支持的有界阻塞队列。在读写操作上都需要锁住整个容器,因此吞吐量与一般的实现是相似的,适合于实现“生产者消费者”模式。

 

基于链表的阻塞队列,同ArrayListBlockingQueue类似,其内部也维持着一个数据缓冲队列(该队列由一个链表构成),当生产者往队列中放入一个数据时,队列会从生产者手中获取数据,并缓存在队列内部,而生产者立即返回;只有当队列缓冲区达到最大值缓存容量时(LinkedBlockingQueue可以通过构造函数指定该值),才会阻塞生产者队列,直到消费者从队列中消费掉一份数据,生产者线程会被唤醒,反之对于消费者这端的处理也基于同样的原理。而LinkedBlockingQueue之所以能够高效的处理并发数据,还因为其对于生产者端和消费者端分别采用了独立的锁来控制数据同步,这也意味着在高并发的情况下生产者和消费者可以并行地操作队列中的数据,以此来提高整个队列的并发性能。

 

ArrayBlockingQueue和LinkedBlockingQueue的区别:

1. 队列中锁的实现不同

    ArrayBlockingQueue实现的队列中的锁是没有分离的,即生产和消费用的是同一个锁;

    LinkedBlockingQueue实现的队列中的锁是分离的,即生产用的是putLock,消费是takeLock

2. 在生产或消费时操作不同

    ArrayBlockingQueue实现的队列中在生产和消费的时候,是直接将枚举对象插入或移除的;

    LinkedBlockingQueue实现的队列中在生产和消费的时候,需要把枚举对象转换为Node<E>进行插入或移除,会影响性能

3. 队列大小初始化方式不同

    ArrayBlockingQueue实现的队列中必须指定队列的大小;

    LinkedBlockingQueue实现的队列中可以不指定队列的大小,但是默认是Integer.MAX_VALUE

 

offer

将元素插入队列,成功返回true,如果当前没有可用的空间,则返回false

offer(E e, long timeout, TimeUnit unit) 

将元素插入队列,在到达指定的等待时间前等待可用的空间

E poll(long timeout, TimeUnit unit) 

获取并移除队列的头部,在指定的等待时间前等待可用的元素

void put(E e) 

将元素插入队列,将等待可用的空间(堵塞)

take() 

获取并移除队列的头部,在元素变得可用之前一直等待(堵塞)

Java代码  收藏代码
  1. public class BlockingQueueTest {  
  2.     private static ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(5true); //最大容量为5的数组堵塞队列  
  3.     //private static LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<Integer>(5);  
  4.       
  5.     private static CountDownLatch producerLatch; //倒计时计数器  
  6.     private static CountDownLatch consumerLatch;  
  7.       
  8.     public static void main(String[] args) {  
  9.         BlockingQueueTest queueTest = new BlockingQueueTest();  
  10.         queueTest.test();  
  11.     }  
  12.       
  13.     private void test(){  
  14.         producerLatch = new CountDownLatch(10); //state值为10  
  15.         consumerLatch = new CountDownLatch(10); //state值为10  
  16.           
  17.         Thread t1 = new Thread(new ProducerTask());  
  18.         Thread t2 = new Thread(new ConsumerTask());  
  19.   
  20.         //启动线程  
  21.         t1.start();  
  22.         t2.start();  
  23.           
  24.         try {  
  25.             System.out.println("producer waiting...");  
  26.             producerLatch.await(); //进入等待状态,直到state值为0,再继续往下执行  
  27.             System.out.println("producer end");  
  28.         } catch (InterruptedException e) {  
  29.             e.printStackTrace();  
  30.         }  
  31.           
  32.         try {  
  33.             System.out.println("consumer waiting...");  
  34.             consumerLatch.await(); //进入等待状态,直到state值为0,再继续往下执行  
  35.             System.out.println("consumer end");  
  36.         } catch (InterruptedException e) {  
  37.             e.printStackTrace();  
  38.         }  
  39.   
  40.         //结束线程  
  41.         t1.interrupt();   
  42.         t2.interrupt();  
  43.           
  44.         System.out.println("end");  
  45.     }  
  46.       
  47.     //生产者  
  48.     class ProducerTask implements Runnable{  
  49.         private Random rnd = new Random();  
  50.           
  51.         @Override  
  52.         public void run() {  
  53.             try {  
  54.                 while(true){  
  55.                     queue.put(rnd.nextInt(100)); //如果queue容量已满,则当前线程会堵塞,直到有空间再继续  
  56.                       
  57.                     //offer方法为非堵塞的  
  58.                     //queue.offer(rnd.nextInt(100), 1, TimeUnit.SECONDS); //等待1秒后还不能加入队列则返回失败,放弃加入  
  59.                     //queue.offer(rnd.nextInt(100));  
  60.                       
  61.                     producerLatch.countDown(); //state值减1  
  62.                     //TimeUnit.SECONDS.sleep(2); //线程休眠2秒  
  63.                 }  
  64.             } catch (InterruptedException e) {  
  65.                 //e.printStackTrace();  
  66.             }  catch (Exception ex){  
  67.                 ex.printStackTrace();  
  68.             }  
  69.         }  
  70.     }  
  71.       
  72.     //消费者  
  73.     class ConsumerTask implements Runnable{  
  74.         @Override  
  75.         public void run() {  
  76.             try {  
  77.                 while(true){  
  78.                     Integer value = queue.take(); //如果queue为空,则当前线程会堵塞,直到有新数据加入  
  79.                       
  80.                     //poll方法为非堵塞的  
  81.                     //Integer value = queue.poll(1, TimeUnit.SECONDS); //等待1秒后还没有数据可取则返回失败,放弃获取  
  82.                     //Integer value = queue.poll();  
  83.                       
  84.                     System.out.println("value = " + value);  
  85.                       
  86.                     consumerLatch.countDown(); //state值减1  
  87.                     TimeUnit.SECONDS.sleep(2); //线程休眠2秒  
  88.                 }  
  89.             } catch (InterruptedException e) {  
  90.                 //e.printStackTrace();  
  91.             } catch (Exception ex){  
  92.                 ex.printStackTrace();  
  93.             }  
  94.         }  
  95.     }  
  96.       
  97. }  

ArrayBlockingQueue和LinkedBlockingQueue的区别及使用

BlockingQueue接口定义了一种阻塞的FIFO queue,每一个BlockingQueue都有一个容量,让容量满时往BlockingQueue中添加数据时会造成阻塞,当容量为空时取元素操作会...
  • USTC_Zn
  • USTC_Zn
  • 2017-02-04 16:56:22
  • 4522

ArrayBlockingQueue跟LinkedBlockingQueue的区别

1.队列中的锁的实现不同        ArrayBlockingQueue中的锁是没有分离的,即生产和消费用的是同一个锁;        LinkedBlockingQueue中的锁是分离的,即...
  • z69183787
  • z69183787
  • 2015-07-21 15:32:32
  • 5498

源码解析:ArrayBlockingQueue和LinkedBlockingQueue的区别

对于ArrayBlockingQueue和LinkedBlockingQueue已经都只是知道如何使用以及他们各自的特点,没有去看看源码到底驶入实现的!因为ArrayBlockingQueue和Lin...
  • Green_shing
  • Green_shing
  • 2015-06-29 17:11:29
  • 1526

Java LinkedBlockingQueue和ArrayBlockingQueue分析

LinkedBlockingQueue是一个链表实现的阻塞队列,在链表一头加入元素,如果队列满,就会阻塞,另一头取出元素,如果队列为空,就会阻塞。 LinkedBlockingQueue内部使用R...
  • hongchangfirst
  • hongchangfirst
  • 2014-09-29 12:09:13
  • 14554

ConcurrentLinkedQueue、AraayBlockingQueue、LinkedBlockingQueue 区别及使用场景

三者区别与联系:联系,三者 都是线程安全的。区别,就是 并发 和 阻塞,前者为并发队列,因为采用cas算法,所以能够高并发的处理;后2者采用锁机制,所以是阻塞的。注意点就是前者由于采用cas算法,虽...
  • fz2543122681
  • fz2543122681
  • 2016-10-03 22:29:02
  • 1635

ArrayBlockingQueue 和 LinkedBlockingQueue 对比

ArrayBlockingQueue 和 LinkedBlockingQueue 对比ArrayBlockingQueue和LinkedBlockingQueue都支持blockingQueue的概念...
  • kang389110772
  • kang389110772
  • 2016-12-19 11:18:09
  • 657

JDK源码分析—— ArrayBlockingQueue 和 LinkedBlockingQueue

目的:本文通过分析JDK源码来对比ArrayBlockingQueue 和LinkedBlockingQueue,以便日后灵活使用。 1. 在Java的Concurrent包中,添加了阻塞队列Bloc...
  • xin_jmail
  • xin_jmail
  • 2014-05-19 10:51:52
  • 23291

ConcurrentLinkedQueue是非阻塞的,blockingqueue是阻塞的

 java.util.concurrent ConcurrentLinkedQueue 类提供了高效的、可伸缩的、线程安全的非阻塞 FIFO 队列。java.util.concurrent...
  • a936676463
  • a936676463
  • 2014-08-12 19:38:44
  • 1290

Java阻塞队列ArrayBlockingQueue和LinkedBlockingQueue实现原理分析(还没看,先马)

转自:Java阻塞队列ArrayBlockingQueue和LinkedBlockingQueue实现原理分析Java中的阻塞队列接口BlockingQueue继承自Queue接口。BlockingQ...
  • x_i_y_u_e
  • x_i_y_u_e
  • 2016-09-12 14:16:31
  • 2609

Java常用的2种阻塞队列ArrayBlockingQueue和LinkedBlockingQueue

ArrayBlockingQueue       基于数组的阻塞队列实现,在ArrayBlockingQueue内部,维护了一个定长数组,以便缓存队列中的数据对象,这是一个常用的阻塞队列,除了一个定长...
  • chichuduxing
  • chichuduxing
  • 2017-04-05 19:11:24
  • 304
收藏助手
不良信息举报
您举报文章:ArrayBlockingQueue和LinkedBlockingQueue的使用
举报原因:
原因补充:

(最多只允许输入30个字)