(八) Java多线程详解之阻塞队列BlockingQueue及队列优先级详解

阻塞队列

阻塞队列与普通队列的区别在于当队列是空时从队列中获取元素的操作将会被阻塞,或者当队列是满时往队列里添加元素的操作会被阻塞。试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列插入新的元素,同样试图往已满的阻塞队列中添加新元素的线程同样也会被阻塞直到其他的线程使队列重新变得空闲起来

BlockingQueue的操作方法

(八) Java多线程详解之阻塞队列BlockingQueue及队列优先级详解_第1张图片

BlockingQueue具有4组不同的方法用于插入移除以及对队列中的元素进行检查,如果请求的操作不能得到立即执行的话,每个方法的表现也不同。这些方法如下:

四组不同的行为方式解释:

抛异常:如果试图的操作无法立即执行,抛一个异常

特定值:如果试图的操作无法立即执行,返回一个特定的值(常常是true/false)

阻塞:如果试图的操作无法立即执行,该方法调用将会发生阻塞,直到能够执行

超时:如果试图的操作无法立即执行,该方法调用将会发生阻塞直到能够执行,但等待时间不会超过给定值。返回一个特定值以告知该操作是否成功(典型的是true/false)

BlockingQueue几种子类实现

3.1 ArrayBlockingQueue:一个有界的阻塞队列,其内部实现是将对象放到一个数组里,有界也就意味着它不能够存储无限多数量的元素,它有一个同一时间能够存储元素数量的上限(因为它是基于数组实现的,一旦初始化大小就无法修改)

3.2 DelayQueue:对元素进行持有直到一个特定的延迟到期,注入其中的元素必须实现java.util.concurrent.Delayed接口

3.3 LinkedBlockingQueue:内部以一个链式结构(链接节点)对其元素进行存储,如果需要的话这一链式结构可以选择一个上限,如果没有定义上限将使用Integer.MAX_VALUE作为上限

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

3.5 SynchronousQueue:一个特殊的队列,它的内部同时只能够容纳单个元素,如果该队列已有一元素的话试图向队列中插入一个新元素的线程将会阻塞,直到另一个线程将该元素从队列中抽走,同样如果该队列为空试图向队列中抽取一个元素的线程将会阻塞,直到另一个线程向队列中插入了一条新的元素

优先级队列PriorityBlockingQueue

这里详细讲一下PriorityBlockingQueue,因为在实际需求中可能会遇到希望后入队的对象先出队,面对这种需求我首先想到的是能不能在队列指定位置添加元素来控制出队的顺序,遗憾队列是线性结构只能在队尾位置进行插入元素,队头位置插入元素,但是PriorityBlockingQueue可能通过实现Comparable接口来修改出队优先级。示例代码如下:

public class ThreadExample20 {
    public static void main(String[] args) {
        Comparator comparator = new Comparator() {
            public int compare(Integer param, Integer param2) {
                if (param > param2) {
                    return 1;
                } else if (param < param2) {
                    return -1;
                } else {
                    return 0;
                }
            }
        };

        BlockingQueue blockingQueue = new PriorityBlockingQueue<>(5, comparator);

        try {
            blockingQueue.put(1);
            blockingQueue.put(23);
            blockingQueue.put(56);
            blockingQueue.put(15);
            blockingQueue.put(8);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        while (true) {
            try {
                System.out.println(blockingQueue.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

程序运行结果:
1
8
15
23
56

你可能感兴趣的:(线程学习笔记)