文档章节

BlockingQueue深入分析

vshcxl
 vshcxl
发布于 2016/12/12 22:13
字数 1315
阅读 11
收藏 1
点赞 0
评论 0

1.BlockingQueue定义的常用方法如下

  抛出异常 特殊值 阻塞 超时
插入 add(e) offer(e) put(e) offer(e,time,unit)
移除 remove() poll() take() poll(time,unit)
检查 element() peek() 不可用 不可用

 

1)add(anObject):把anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则招聘异常

2)offer(anObject):表示如果可能的话,将anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则返回false.

3)put(anObject):把anObject加到BlockingQueue里,如果BlockQueue没有空间,则调用此方法的线程被阻断直到BlockingQueue里面有空间再继续.

4)poll(time):取走BlockingQueue里排在首位的对象,若不能立即取出,则可以等time参数规定的时间,取不到时返回null

5)take():取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到Blocking有新的对象被加入为止

其中:BlockingQueue 不接受null 元素。试图add、put 或offer 一个null 元素时,某些实现会抛出NullPointerException。null 被用作指示poll 操作失败的警戒值。 

 

2、BlockingQueue的几个注意点

【1】BlockingQueue 可以是限定容量的。它在任意给定时间都可以有一个remainingCapacity,超出此容量,便无法无阻塞地put 附加元素。没有任何内部容量约束的BlockingQueue 总是报告Integer.MAX_VALUE 的剩余容量。

【2】BlockingQueue 实现主要用于生产者-使用者队列,但它另外还支持Collection 接口。因此,举例来说,使用remove(x) 从队列中移除任意一个元素是有可能的。然而,这种操作通常 会有效执行,只能有计划地偶尔使用,比如在取消排队信息时。

【3】BlockingQueue 实现是线程安全的。所有排队方法都可以使用内部锁或其他形式的并发控制来自动达到它们的目的。然而,大量的 Collection 操作(addAll、containsAll、retainAll 和removeAll)没有 必要自动执行,除非在实现中特别说明。因此,举例来说,在只添加了c 中的一些元素后,addAll(c) 有可能失败(抛出一个异常)。

【4】BlockingQueue 实质上不支持使用任何一种“close”或“shutdown”操作来指示不再添加任何项。这种功能的需求和使用有依赖于实现的倾向。例如,一种常用的策略是:对于生产者,插入特殊的end-of-stream 或poison 对象,并根据使用者获取这些对象的时间来对它们进行解释。

 

3、简要概述BlockingQueue常用的四个实现类

 

 

1)ArrayBlockingQueue:规定大小的BlockingQueue,其构造函数必须带一个int参数来指明其大小.其所含的对象是以FIFO(先入先出)顺序排序的.

2)LinkedBlockingQueue:大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的BlockingQueue有大小限制,若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定.其所含的对象是以FIFO(先入先出)顺序排序的

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

4)SynchronousQueue:特殊的BlockingQueue,对其的操作必须是放和取交替完成的.

    

其中LinkedBlockingQueue和ArrayBlockingQueue比较起来,它们背后所用的数据结构不一样,导致LinkedBlockingQueue的数据吞吐量要大于ArrayBlockingQueue,但在线程数量很大时其性能的可预见性低于ArrayBlockingQueue.  

 

下面主要看一下ArrayBlockingQueue的源码:


 

public boolean offer(E e) {      
        if (e == null) throw new NullPointerException();      
        final ReentrantLock lock = this.lock;//每个对象对应一个显示的锁      
        lock.lock();//请求锁直到获得锁(不可以被interrupte)      
        try {      
            if (count == items.length)//如果队列已经满了      
                return false;      
            else {      
                insert(e);      
                return true;      
            }      
        } finally {      
            lock.unlock();//      
        }      
}      
看insert方法:      
private void insert(E x) {      
        items[putIndex] = x;      
        //增加全局index的值。      
        /*    
        Inc方法体内部:    
        final int inc(int i) {    
        return (++i == items.length)? 0 : i;    
            }    
        这里可以看出ArrayBlockingQueue采用从前到后向内部数组插入的方式插入新元素的。如果插完了,putIndex可能重新变为0(在已经执行了移除操作的前提下,否则在之前的判断中队列为满)    
        */     
        putIndex = inc(putIndex);       
        ++count;      
        notEmpty.signal();//wake up one waiting thread      
}  
public void put(E e) throws InterruptedException {      
        if (e == null) throw new NullPointerException();      
        final E[] items = this.items;      
        final ReentrantLock lock = this.lock;      
        lock.lockInterruptibly();//请求锁直到得到锁或者变为interrupted      
        try {      
            try {      
                while (count == items.length)//如果满了,当前线程进入noFull对应的等waiting状态      
                    notFull.await();      
            } catch (InterruptedException ie) {      
                notFull.signal(); // propagate to non-interrupted thread      
                throw ie;      
            }      
            insert(e);      
        } finally {      
            lock.unlock();      
        }      
}  
public boolean offer(E e, long timeout, TimeUnit unit)      
        throws InterruptedException {      
     
        if (e == null) throw new NullPointerException();      
    long nanos = unit.toNanos(timeout);      
        final ReentrantLock lock = this.lock;      
        lock.lockInterruptibly();      
        try {      
            for (;;) {      
                if (count != items.length) {      
                    insert(e);      
                    return true;      
                }      
                if (nanos <= 0)      
                    return false;      
                try {      
                //如果没有被 signal/interruptes,需要等待nanos时间才返回      
                    nanos = notFull.awaitNanos(nanos);      
                } catch (InterruptedException ie) {      
                    notFull.signal(); // propagate to non-interrupted thread      
                    throw ie;      
                }      
            }      
        } finally {      
            lock.unlock();      
        }      
    }      
public boolean add(E e) {      
    return super.add(e);      
}      
父类:      
public boolean add(E e) {      
        if (offer(e))      
            return true;      
        else     
            throw new IllegalStateException("Queue full");      
    }    

该类中有几个实例变量:takeIndex/putIndex/count

用三个数字来维护这个队列中的数据变更:      
    /** items index for next take, poll or remove */     
    private int takeIndex;      
    /** items index for next put, offer, or add. */     
    private int putIndex;      
    /** Number of items in the queue */     
    private int count;    

 

本文转载自:http://blog.csdn.net/tayanxunhua/article/details/20962307

共有 人打赏支持
vshcxl
粉丝 21
博文 282
码字总数 34755
作品 0
浦东
高级程序员
集合框架 Queue---BlockingQueue详解

本例介绍一个特殊的队列:BlockingQueue,如果BlockingQueue是空的,从BlockingQueue取东西的操作将会被阻断进入等待状态,直到BlockingQueue进了东西才会被唤醒,同样,如果BlockingQueue是...

长平狐
2012/11/28
587
0
BlockingQueue详解

本例再次实现前面介绍的篮子程序,不过这个篮子中最多能放得苹果数不是1,可以随意指定。当篮子满时,生产者进入等待状态,当篮子空时,消费者等待。 BlockingQueue定义的常用方法如下: ad...

wow863597
2016/05/09
53
0
JDK5.0新特性系列---11.6线程 BlockingQueue

importjava.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /**......

tavenli
2011/12/17
0
0
java 队列阻塞方法ArrayBlockingQueue学习

本例介绍一个特殊的队列:BlockingQueue,如果BlockQueue是空的,从BlockingQueue取东西的操作将会被阻断进入等待状态,直到BlockingQueue进了东西才会被唤醒.同样,如果BlockingQueue是满的,任何...

孟飞阳
2016/07/01
23
0
使用BlockingQueue的生产者消费者模式

BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题。通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利。使用场景。 首先它是一个队列,...

雪童子
2016/04/24
0
0
Java阻塞队列_BlockingQueue

Java阻塞队列_BlockingQueue 以上是BlockingQueue所有的方法。。 add(anObject):把anObject加到BlockingQueue里,如果BlockingQueue可以容纳,则返回true,否则抛出异常。 offer(anObject):...

秋风醉了
2014/08/07
127
0
使用Java的BlockingQueue实现生产者-消费者

BlockingQueue也是java.util.concurrent下的主要用来控制线程同步的工具。 BlockingQueue有四个具体的实现类,根据不同需求,选择不同的实现类 1、ArrayBlockingQueue:一个由数组支持的有界阻...

mrliuze
2015/08/11
0
0
Java中Queue和BlockingQueue的区别

内容主要来自jdk的api,大家可参考jdkapi 1.BlockingQueue:支持两个附加操作的 Queue,这两个操作是:检索元素时等待队列变为非空,以及存储元素时等待空间变得可用。 2.BlockingQueue 不接受...

红薯
2010/04/03
607
3
blockingqueue学习笔记

一。接口blockingqueue 1>BlockingQueue是一种特殊的queue,特殊性如下: 若blockingQueue是空的,从该队列中取东西的操作将会被阻断进入等待状态,知道blockingqueue进了新货才会被唤醒。 ...

tongqu
2016/02/17
30
0
Java多线程-工具篇-BlockingQueue

前言: 在新增的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题。通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利...

空云万里晴
2016/06/16
54
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Call to undefined function Workerman\posix_getpid

workerman 在centos下报PHP Fatal error: Call to undefined function Workerman\posix_getpid posix在下面这个包中php-process...

dragon_tech
6分钟前
0
0
mysql 7.4 创建表 时  所建表 字段太多 导致失败

报错:[Err] 1118 - Row size too large (> 8126). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline. 解决方法:把表的引......

qimh
8分钟前
0
0
语法补漏

1.if...elif...else... 代码示例: test=10 if test>9: print(1) elif test>8: print(2) elif test>7: print(3) else: print('nothing') 输出代码: 1...

十年磨一剑3344
8分钟前
0
0
Python -re模块及正则表达式解析

传送门: https://blog.csdn.net/pipisorry/article/details/25909899 ps:上面文章中"命名分组"的语法格式不能执行。正确的如下: (?P<name>正则表达式) #name是一个合法的标识符 除了使用别名...

一口今心
16分钟前
0
0
mybatis中session.getMapper方法源码分析

0开始代码AuthorMapper mapper = session.getMapper(AuthorMapper.class); 1 DefaultSqlSession类 @Override public <T> T getMapper(Class<T> type) { //最后会去调用MapperRegistry.getMap......

writeademo
24分钟前
1
0
spring cloud zuul网关的作用

zuul一般有两大作用,1是类似于Nginx的网址重定向,但zuul的重定向的一般是整个spring cloud里在Eureka注册中心的模块. zuul: ignored-services: '*' sensitiveHeaders: routes: ...

算法之名
24分钟前
9
0
java按比例之原图生成缩略图

package com.wxp.test; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import javax.imageio.ImageIO; import sun.......

恋码之子
34分钟前
1
0
SpringCloud 微服务 (十五) 服务容错 Hystrix

壹 工作中的微服务架构,某个服务通常会被多个服务调用或者多层调用完成需求,如果某个服务不可用,导致一个系统功能不可用或者服务直接没用了的情况,这种情况称为雪崩效应 有A服务调用B服务,B服...

___大侠
36分钟前
1
0
Spring框架中的设计模式(五)

Spring框架中的设计模式(五) 通过以前的4篇文章,我们看到Spring采用了大量的关于创建和结构方面的设计模式。本文将描述属于行为方面的两种设计模式:命令和访问者。 前传: Spring框架中的...

瑞查德-Jack
39分钟前
1
0
解决phpstorm运行很卡问题!

phpStorm一旦达到这个临界值,所有智能提示、自动补全都失效了 这TM就很尴尬了,顿时感觉自己就是个废人了,纯手写代码跟便秘一样 众所周知phpStorm基于JAVA,那么这个内存限制肯定跟JAVA的虚...

sjcehui2010
42分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部