您当前的位置: 首页 > 

庄小焱

暂无认证

  • 2浏览

    0关注

    805博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

JDK源码——BlockingQueue类

庄小焱 发布时间:2021-11-26 23:14:50 ,浏览量:2

摘要

阻塞队列 (BlockingQueue)是Java util.concurrent包下重要的数据结构,BlockingQueue提供了线程安全的队列访问方式:当阻塞队列进行插入数据时,如果队列已满,线程将会阻塞等待直到队列非满;从阻塞队列取数据时,如果队列已空,线程将会阻塞等待直到队列非空。并发包下很多高级同步类的实现都是基于BlockingQueue实现的。阻塞队列原理:其实阻塞队列实现阻塞同步的方式很简单,使用的就是lock锁的多条件阻塞控制。使用BlockingQueue封装了根据条件阻塞线程的过程,而我们就不用关心繁琐的await/signal操作了。

BlockingQueue的定义

BlockingQueue 是个接口,你需要使用它的实现之一来使用BlockingQueue,java.util.concurrent包下具有以下 BlockingQueue 接口的实现类:

多线程中不能使用的if做判断。而需要使用while来实现多线程。

当阻塞队列是空时,从队列中获取元素的操作将会被阻塞。当阻塞队列是满时,往队列里添加元素的操作将会被阻塞。在多线程领域:所谓阻塞,在某些情况下会挂起线程(即阻塞),一旦条件满足,被挂起的线程又会自动被唤醒

BlockingQueue的优点

程序员本身不需要关心什么时候需要阻寨线程,什么时候需要唤醒线程,因为这一切BlockingQueue都给你一手包办了。在concurrent包发布以前,在多线程环境下,我们每个程序员都必须去自己控制这些细节,尤其还要兼顾效率和线程安全,而这会给我们的程序带来不小的复杂度。

插入add(e)offer(e)put(e)offer(e,time,unit)移除remove()poll()take()poll(time,unit)检查element()peek()不可用不可用 异常抛出

当阻塞队列满时,再往队列里add插入元素会抛IllegalStateException: Queue full当阻塞队列空时,再往队列里remove移除元素会抛NoSuchElementException

特殊值

插入方法,成功ture失败false 移除方法,成功返回出队列的元素,队列里面没有就返回null

一直阻塞

当阻塞队列满时,生产者线程继续往队列里put元素,队列会一直阻塞生产线程直到put数据or响应中断退出。当阻塞队列空时,消费者线程试图从队列里take元素,队列会一直阻塞消费者线程直到队列可用。

超时退出

当阻塞队列满时,队列会阻塞生产者线程一定时间,超过后限时后生产者线程会退出

ArrayBlockingQueue

由数组结构组成的有界阻塞队列,ArrayBlockingQueue 是一个有界的阻塞队列,其内部实现是将对象放到一个数组里。有界也就意味着,它不能够存储无限多数量的元素。它有一个同一时间能够存储元素数量的上限。你可以在对其初始化的时候设定这个上限,但之后就无法对这个上限进行修改了(译者注:因为它是基于数组实现的,也就具有数组的特性:一旦初始化,大小就无法修改)。

LinkedBlockingQueue

由链表结构组成的有界(但大小默认值为Integer.MAX_VALUE)阻塞队,LinkedBlockingQueue 内部以一个链式结构(链接节点)对其元素进行存储。如果需要的话,这一链式结构可以选择一个上限。如果没有定义上限,将使用 Integer.MAX_VALUE 作为上限。

PriorityBlockingQueue

支持优先级排序的无界阻塞队列,PriorityBlockingQueue 是一个无界的并发队列。它使用了和类 java.util.PriorityQueue 一样的排序规则。你无法向这个队列中插入 null 值。所有插入到 PriorityBlockingQueue 的元素必须实现 java.lang.Comparable 接口。因此该队列中元素的排序就取决于你自己的 Comparable 实现。

DelayQueue

使用优先级队列实现的延迟无界阻塞队列,DelayQueue 对元素进行持有直到一个特定的延迟到期。注入其中的元素必须实现 java.util.concurrent.Delayed 接口。

SynchronousQueue

不存储元素的阻塞队列,也即单个元素的队列,SynchronousQueue没有容量。与其他BlockingQueue不同,SynchronousQueue是一个不存储元素的BlockingQ,每一个put操作必须要等待一个take操作,否则不能继续添加元素,反之亦然。

package com.zhuangxiaoyan.jdk.juc.JucLock;

import java.sql.Timestamp;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;

/**
 * @Classname BlockingQueueDemo
 * @Description TODO
 * @Date 2021/11/26 23:06
 * @Created by xjl
 */
public class BlockingQueueDemo {
    public static void main(String[] args) {
        BlockingQueue blockingQueue=new SynchronousQueue();
        new Thread(()->{
            try {
                System.out.println(Thread.currentThread().getName()+"\t put 1");
                blockingQueue.put("1");
                System.out.println(Thread.currentThread().getName()+"\t put 2");
                blockingQueue.put("");
                System.out.println(Thread.currentThread().getName()+"\t put 3");
                blockingQueue.put("");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"AAA").start();

        new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(5);
                System.out.println(Thread.currentThread().getName()+"\t "+blockingQueue.take());
                TimeUnit.SECONDS.sleep(5);
                System.out.println(Thread.currentThread().getName()+"\t "+blockingQueue.take());
                TimeUnit.SECONDS.sleep(5);
                System.out.println(Thread.currentThread().getName()+"\t "+blockingQueue.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"BBB").start();
    }
}
LinkedTransferQueue

由链表结构组成的无界阻塞队列。

 LinkedBlockingDeque

由链表结构组成的双向阻塞队列。

博文参考
关注
打赏
1657692713
查看更多评论
立即登录/注册

微信扫码登录

0.0402s