阻塞队列

一、阻塞队列的概念
阻塞队列和一般队列一样,都是用于存取数据的容器,只不过多了两个附加的操作:在队列为空时,获取元素的线程会等待队列变为非空;在队列到达指定的容量时,存储数据的线程会等待队列可用,具体可以参考生产消费者模型,生产者相当于向队列添加元素的线程,当元素到达一定数量时,将不再添加元素,消费者相当于是从队列取走元素的线程,当队列为空时,就会等待生产者重新向队列添加元素。所以阻塞队列就相当于生产者存放元素的容器,而消费者就是从容器里取走元素。

二、为什么要用阻塞队列
在多线程中,在某些情况下会挂起线程(即阻塞),一旦条件满足,线程就会自动唤醒,参考生产者消费者模型,所以有了阻塞队列,我们不用去担心什么时候阻塞或者唤醒线程,都由阻塞队列来完成

三、JDK提供的几种阻塞队列
1.ArrayBlockingQueue:数组组成的有界阻塞队列,此队列按照先进先出的原则对元素进行排序,默认不保证线程公平,如果队列满了,那么队列外面被阻塞的线程对队列的访问顺序不会是先阻塞,先访问的(即线程公平)。
2.LinkedBlockingQueue:由链表组成的有界阻塞队列,按照先进先出的原则对元素进行排列。
3.PriorityBlockingQueue:支持优先级的无界有界队列
4.DelayBlockingQueue:支持延时获取元素的无界阻塞队列。
5.SynchronousQueue:不储存元素的阻塞队列,每一个put必须等待一个take操作,否则不能添加元素,支持线程公平。
6.LinkedTransferQueue:由链表组成的无界TransferQueue队列,较其他队列来说多了tryTransfer和transfer方法。
transfer:如果消费者(获取元素的线程)正在等待接收元素(take或者poll),transfer可以把生产者(添加元素的线程)所要添加的元素立即传给消费者,如果没有消费者正在等待接收元素,则将元素放在队列的末尾,并等待该元素被消费了才返回。
tryTransfer:用来测试生产者传入的元素能否直接传输给消费者,如果没有消费者等待,则返回false,无论消费者是否接收,不会等待,而是立即返回结果。
7.LinkedBlockingQueue:链表的双向阻塞队列,优点在于多线程的环境下,可以减少一半的资源竞争。

四、阻塞队列中的核心方法
1.抛出异常的方法:add() remove() element() 当不满足条件时会抛出异常
2.返回特殊值的方法:offer() poll() peek() 当操作后会返回结果
3.阻塞的方法:put(E e) take() 不满足添加时,会阻塞,直到满足条件
4.超时的方法:offer(e,time,unit) poll(time,unit) 设置了操作时间,如果在规定时间里还没有操作成功,会中断。
五、模拟阻塞队列的实现

public class MyBlockingQueue<E> {

    // 队列元素
    private Object[] elements;
    // 添加元素时的位置
    private int addIndex;
    // 取出元素时的位置
    private int takeIndex;
    // 队列大小
    private int size;

    public MyBlockingQueue(int capacity){
        elements = new Object[capacity];
    }

    public synchronized E poll(){
        E element = null;
        try {
            while (size == 0)   //当队列里元素为空时,获取元素的线程等待,直到队列非空时,才获取元素
                wait();
            element = (E) elements[takeIndex];
            takeIndex = (takeIndex + 1) % elements.length;
            size--;
            notifyAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return element;
    }

    public synchronized void offer(E element){
        try {
            while (size == elements.length){ //当对队列里的元素满容量时,添加元素的线程等待,直到队列容量非满才添加元素
                wait();
            }
            elements[addIndex] = element;
            addIndex = (addIndex+1) % elements.length;
            size++;
            notifyAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值