BlockingQueue接口定义了一种阻塞的FIFO queue,每一个BlockingQueue都有一个容量,让容量满时往BlockingQueue中添加数据时会阻塞,当容量为空时取元素操作会阻塞。
 
ArrayBlockingQueue是一个由数组支持的有界阻塞队列。在读写操作上都需要锁住整个容器,因此吞吐量与一般的实现是相似的,适合于实现“生产者消费者”模式。
 
LinkedBlockingQueue是一个基于链表的阻塞队列,同ArrayListBlockingQueue类似,其内部维持着一个由一个链表构成的数据缓冲队列,当生产者往队列中放入一个数据时,队列会从生产者手中获取数据,并缓存在队列内部,而生产者立即返回;只有当队列缓冲区达到最大值缓存容量时(LinkedBlockingQueue可以通过构造函数指定该值),才会阻塞生产者队列,直到消费者从队列中消费掉一份数据,生产者线程会被唤醒,反之对于消费者这端的处理也基于同样的原理。而LinkedBlockingQueue之所以能够高效的处理并发数据,还因为其对于生产者端和消费者端分别采用了独立的锁来控制数据同步,这也意味着在高并发的情况下生产者和消费者可以并行地操作队列中的数据,以此来提高整个队列的并发性能。
 
ArrayBlockingQueue和LinkedBlockingQueue的区别:
1. 队列中锁的实现不同
    ArrayBlockingQueue实现的队列中的锁是没有分离的,即生产和消费用的是同一个锁;
    LinkedBlockingQueue实现的队列中的锁是分离的,即生产用的是putLock,消费是takeLock
2. 在生产或消费时操作不同
    ArrayBlockingQueue实现的队列中在生产和消费的时候,是直接将枚举对象插入或移除的;
    LinkedBlockingQueue实现的队列中在生产和消费的时候,需要把枚举对象转换为Node<E>进行插入或移除,会影响性能
3. 队列大小初始化方式不同
    ArrayBlockingQueue实现的队列中必须指定队列的大小;
    LinkedBlockingQueue实现的队列中可以不指定队列的大小,但是默认是Integer.MAX_VALUE

public class BlockingQueueTest {

    //最大容量为5的数组堵塞队列
    private static ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(5, true);
    //private static LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<Integer>(5);
    private static CountDownLatch producerLatch; //生产者倒计时计数器
    private static CountDownLatch consumerLatch;//消费者倒计时计数器
    public static void main(String[] args) {
        producerLatch = new CountDownLatch(10); //state值为10
        consumerLatch = new CountDownLatch(10); //state值为10
        new Thread(new ProducerTask()).start();
        new Thread(new ConsumerTask()).start();
        try {
            System.out.println("producer waiting...");
            producerLatch.await(); //进入等待状态,直到state值为0,再继续往下执行
            System.out.println("producer end");
            System.out.println("consumer waiting...");
            consumerLatch.await(); //进入等待状态,直到state值为0,再继续往下执行
            System.out.println("consumer end");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("end");
    }
//******************************************************************************************
    //生产者
    private static class ProducerTask implements Runnable {
        private Random rnd = new Random();
        @Override
        public void run() {
            try {
                while (true) {
                    queue.put(rnd.nextInt(100)); //如果queue容量已满,则当前线程会堵塞,直到有空间再继续
                    //offer方法为非堵塞的
                    //queue.offer(rnd.nextInt(100), 1, TimeUnit.SECONDS); //等待1秒后还不能加入队列则返回失败,放弃加入
                    //queue.offer(rnd.nextInt(100));
                    producerLatch.countDown(); //state值减1
                    //TimeUnit.SECONDS.sleep(2); //线程休眠2秒
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
    //消费者
    private static class ConsumerTask implements Runnable {
        @Override
        public void run() {
            try {
                while (true) {
                    Integer value = queue.take(); //如果queue为空,则当前线程会堵塞,直到有新数据加入
                    //poll方法为非堵塞的
                    //Integer value = queue.poll(1, TimeUnit.SECONDS); //等待1秒后还没有数据可取则返回失败,放弃获取
                    //Integer value = queue.poll();
                    System.out.println("value = " + value);
                    consumerLatch.countDown(); //state值减1
                    TimeUnit.SECONDS.sleep(2); //线程休眠2秒
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }

}


BlockingQueue接口的更多相关文章

  1. 生产者-消费者中的缓冲区:BlockingQueue接口

    BlockingQueue接口使用场景相信大家对生产者-消费者模式不陌生,这个经典的多线程协作模式,最简单的描述就是生产者线程往内存缓冲区中提交任务,消费者线程从内存缓冲区里获取任务执行.在生产者-消 ...

  2. 并发队列 ConcurrentLinkedQueue 及 BlockingQueue 接口实现的四种队列

    队列是一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作.进行插入操作的端称为队尾,进行删除操作的端称为队头.队列中没有元素时,称为空队列. 在队列这 ...

  3. Java.util.concurrent包学习(一) BlockingQueue接口

    JDK1.7 BlockingQueue<E>接口 (extends Queue<E>) 所有父接口:Collection<E>,Iterable<E> ...

  4. Java:concurrent包下面的Collection接口框架图( CopyOnWriteArraySet, CopyOnWriteArrayList,ConcurrentLinkedQueue,BlockingQueue)

    Java集合大致可分为Set.List和Map三种体系,其中Set代表无序.不可重复的集合:List代表有序.重复的集合:而Map则代表具有映射关系的集合.Java 5之后,增加了Queue体系集合, ...

  5. ArrayBlockingQueue,BlockingQueue分析

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

  6. 并发队列之:BlockingQueue和ConcurrentLinkedQueue

    一.并行和并发区别: 并行:是指两者同时执行一件事.比如赛跑,两个人都在不停的往前跑: 并发:是指资源有限的情况下,两者交替轮流使用资源.比如一段路(单核CPU资源)同时只能过一个人,A走一段后,让给 ...

  7. 项目积累——Blockingqueue,ConcurrentLinkedQueue,Executors

    背景 通过做以下一个小的接口系统gate,了解一下mina和java并发包里的东西.A系统为javaweb项目,B为C语言项目,gate是本篇须要完毕的系统. 需求 1. A为集群系统,并发较高,会批 ...

  8. java.util.concurrent BlockingQueue

    BlockingQueue 它实现了Queue接口.它是A BlockingQueue with one thread putting into it, and another thread taki ...

  9. java并发包——阻塞队列BlockingQueue及源码分析

    一.摘要 BlockingQueue通常用于一个线程在生产对象,而另外一个线程在消费这些对象的场景,例如在线程池中,当运行的线程数目大于核心的线程数目时候,经常就会把新来的线程对象放到Blocking ...

随机推荐

  1. GitHub-修改以下host-ip可加快访问速度

    #GitHub START 207.97.227.239    github.com 204.232.175.94    gist.github.com 107.21.116.220    help. ...

  2. js变量声明与赋值以及函数声明

    if (!("a" in window)) { var a = 1; } alert(a); 结果:undefined 分析: 首先,所有的全局变量都是window的属性,语句 v ...

  3. python学习第一课要点记录

    写在要点之前的一段话,留给将来的自己:第一次参加编程的培训班,很兴奋很激动,之前都是自己在网上找免费的视频来看,然后跟着写一些课程中的代码,都是照着模子写,没有自己过多的思考.感觉这样学不好,除了多写 ...

  4. 转:PHP 使用ZipArchive压缩文件并下载

    原文来自于:http://courages.us/archives/176 网站上需要提供一些打印数据给用户下载,这些文件每次都需要重新生成,因为随时都会有新的数据产生.网络上关于PHP的压缩功能实现 ...

  5. 14.4.2 Change Buffer 延迟写

    14.4.2 Change Buffer change buffer 是一个特殊的数据结构 用于cahce 改变的secondary index pages 当被影响的pages 不在buffer p ...

  6. Silverlight获取DataGrid选中的行数据

    注意触发的事件为:CurrentCellChanged后台代码: /// <summary> /// 获取datagrid当前选中的单元格数据 /// 如果绑定的数据源为实体的话默认选中的 ...

  7. app开发历程——android手机显示服务器端图片思路

    以前自己都不知道怎么去显示服务器端的图片,还好在apkbus论坛上找到一个特别简单的例子.虽然一天天忙忙碌碌,但是自己内心其实有一种想逃的心里,说不定哪天就会冒出来. 1.首先服务器端图片 这里的Im ...

  8. 进程间通讯aidl

    进程间通讯(aidl) 1.首先定义一个接口 2.把这个接口的文件扩展名改为xxx.aidl 3.写一个MyService类继承自Service类重新里面的方法, 4.在MyService类定义一个内 ...

  9. POJ_3356——最短编辑距离,动态规划

    Description Let x and y be two strings over some finite alphabet A. We would like to transform x int ...

  10. 一个linux下socket编程的例子,client连server

    关于socket编程,以下文章写得比较好:http://www.cnblogs.com/xudong-bupt/archive/2013/12/29/3483059.html 1. accept()函 ...