java.util.concurrent包学习之阻塞队列

前言:

  阻塞队列是jdk5 java.util.concurrent包中五个模块之一,一般用于消费者、生产者的情景,与一般队列的不同就是阻塞队列内部加入了Lock和Condition可以在某个线程试图向队列添加元素而该队列已经满时,或者从队列移出元素而队列为空时,自动阻塞该线程。

阻塞队列的作用和使用场景

  所以在协调多个线程之间的合作时,阻塞队列是一个有用的工具。生产线程可以周期性地将中间结果存储在阻塞队列中,而消费线程移除中间结果并加以逻辑处理。阻塞队列最大的作用就是可以自动平衡负载,因为如果生产者线程集运行得比消费者线程集慢,消费者线程就会发生阻塞,反之也是一样。假设一个场景:我们写一个监控文件变化的程序,开一个线程获取变化了的文件名,拿到之后我们会做解析,查找数据库等等其他操作。如果我们对这两个操作分开统计它们的处理时间,会发现后面的解析需要的时间远远大于前面得到文件名的时间。如果这个线程每一秒轮询一次,而解析查询操作有可能会超出一秒,这样就会让大量的变化文件来不及处理。这个使用就需要用到阻塞线程了,可以使用生产线程来进行文件变化检测,而多个消费线程来进行文件处理操作。

JDK 7 提供了7个阻塞队列

**1、ArrayBlockingQueue **数组结构组成的有界阻塞队列。
此队列按照先进先出(FIFO)的原则对元素进行排序,但是默认情况下不保证线程公平的访问队列,即如果队列满了,那么被阻塞在外面的线程对队列访问的顺序是不能保证线程公平(即先阻塞,先插入)的。

2、LinkedBlockingQueue一个由链表结构组成的有界阻塞队列
此队列按照先出先进的原则对元素进行排序

3、PriorityBlockingQueue 支持优先级的无界阻塞队列

4、DelayQueue 支持延时获取元素的无界阻塞队列,即可以指定多久才能从队列中获取当前元素

5、SynchronousQueue不存储元素的阻塞队列,每一个put必须等待一个take操作,否则不能继续添加元素。并且他支持公平访问队列。

6、LinkedTransferQueue由链表结构组成的无界阻塞TransferQueue队列。相对于其他阻塞队列,多了tryTransfer和transfer方法

transfer方法
  如果当前有消费者正在等待接收元素(take或者待时间限制的poll方法),transfer可以把生产者传入的元素立刻传给消费者。如果没有消费者等待接收元素,则将元素放在队列的tail节点,并等到该元素被消费者消费了才返回。

tryTransfer方法
  用来试探生产者传入的元素能否直接传给消费者。,如果没有消费者在等待,则返回false。和上述方法的区别是该方法无论消费者是否接收,方法立即返回。而transfer方法是必须等到消费者消费了才返回。

7、LinkedBlockingDeque链表结构的双向阻塞队列,优势在于多线程入队时,减少一半的竞争。

阻塞队列的方法

方法 正常动作 特殊情况下动作
add 添加一个元素 如果队列满,则抛出IllegalStateException异常
offer 添加一个元素并返回bollean 如果队列满,返回false
put 添加一个元素 如果队列满,则阻塞该线程
element 返回队列的头元素 如果队列为空,则抛出NoSuchElementException
peek 返回队列的头元素 如果队列为空,则返回null
poll 移除并返回队列的头元素 如果队列为空,返回null
remove 移除并返回队列的头元素 如果队列为空,则抛出NoSuchElementException
take 移除并返回队列的头元素 如果队列为空 ,则阻塞该线程

阻塞队列测试使用

public class BlockQueueTest {

    private static BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<String>(10);

    /**
     * 消费者线程,每一秒消费一次
     */
  static   class Consumer implements  Runnable{

        BlockingQueue queue;
        public  Consumer(BlockingQueue queue){
            this.queue = queue;
        }
        public void run() {
            System.out.println("开始消费----");
            while (true){
                try {
                    Object poll = queue.take();
                    Thread.sleep(500);
                    System.out.println(Thread.currentThread().getName()+"消费"+(String)poll);
                } catch (InterruptedException e) {
                    //被中断,捕获后清除中断状态
                    Thread.currentThread().interrupt();
                }
            }
        }
    }

   static class Producer implements Runnable{

        BlockingQueue queue;

        Producer(BlockingQueue queue){
            this.queue = queue;
        }

        public void run() {
            System.out.println("开始生产-------");
            while (true){
                try {
                    queue.put("test");
                    System.out.println("生产线程生产test");
                } catch (InterruptedException e) {
                    //捕获中断,清除中断状态
                    Thread.currentThread().interrupt();
                }
            }
        }
    }
    public static void main(String[] args) {
        //开启生产线程
        new Thread(new Producer(blockingQueue)).start();
        //开启三个消费线程
        new Thread(new Consumer(blockingQueue)).start();
        new Thread(new Consumer(blockingQueue)).start();
        new Thread(new Consumer(blockingQueue)).start();
    }

参考

  • 《Java核心技术》
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,744评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,505评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,105评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,242评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,269评论 6 389
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,215评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,096评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,939评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,354评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,573评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,745评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,448评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,048评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,683评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,838评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,776评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,652评论 2 354

推荐阅读更多精彩内容