常见的BlockingQueue有哪些?
ArrayBlockingQueue
基于数组结构,构造函数时需要指定最大容量,当队列里的元素超过最大容量时,要么阻塞,要么直接返回结果,写入数据时不能写入null。
阻塞式写入
向队尾写入数据,队列满后一直阻塞,除非有消费了,或者线程中断
put(E e)
向队尾写入数据,队列满后开始阻塞,阻塞指定时间后,结束阻塞,不会写入成功,返回结果false
offer(E e, long timeout, TimeUnit unit)
非阻塞式写入
当队列满了后,直接抛出异常
add(E e)
当队列满了后,直接返回false,不抛出异常
offer(E e)
阻塞式读取
从队列头部获取数据,并且该数据会从队列头部移除,当队列为空时执行take方法的线程将进入阻塞,直到有其他线程写入新的数据,或者当前线程被执行了中断操作
E take()
从队列头部获取数据,并且该数据会从队列头部移除,如果队列中没有任何元素时则执行该方法,当前线程会阻塞指定的时间,直到在此期间有新的数据写入,或者阻塞的当前线程被其他线程中断,当线程由于超时退出阻塞时,返回值为null
E poll(long timeout, TimeUnit unit)
非阻塞式读取
从队列头部获取数据并且该数据会从队列头部移除,当队列为空时,该方法不会使得当前线程进入阻塞,而是返回null值。
E poll()
直接从队列头部获取一个数据,但是并不能从队列头部移除数据,当队列为空时,该方法不会使得当前线程进入阻塞,而是返回null值。
E peek():
PriorityBlockingQueue
PriorityBlockingQueue优先级阻塞队列是一个“无边界”阻塞队列,用法与ArrayBlockingQueue类似,该队列会根据某种规则(Comparator)对插入队列尾部的元素进行排序,因此该队列将不会遵循FIFO约束。
-
排序且无边界的队列只要应用程序的内存足够使用,理论上,PriorityBlockingQueue存放数据的数量是“无边界”的,在PriorityBlockingQueue内部维护了一个Object的数组,随着数据量的不断增多,该数组也会进行动态地扩容。在构造PriorityBlockingQueue时虽然提供了一个整数类型的参数,但是该参数所代表的含义与ArrayBlockingQueue完全不同,前者是构造PriorityBlockingQueue的初始容量,后者指定的整数类型参数则是ArrayBlockingQueue的最大容量。
-
元素必须实现了Comparator接口的,默认情况下,优先级最小的数据元素将被放在队列头部,优先级最大的数据元素将被放在队列尾部。
-
不存在阻塞写方法由于PriorityBlockingQueue是“无边界”的队列,因此将不存在对队列上限临界值的控制,在PriorityBlockingQueue中,添加数据元素的所有方法都等价于offer方法,从队列的尾部添加数据,但是该数据会根据排序规则对数据进行排序。
LinkedBlockingQueue
LinkedBlockingQueue队列的边界可选性是通过构造函数来决定的,当我们在创建LinkedBlockingQueue对象时,使用的是默认的构造函数,那么该队列的最大容量将为Integer的最大值(所谓的“无边界”),当然开发者可以通过指定队列最大容量(有边界)的方式创建队列。 其用法与ArrayBlockingQueue一样。
SynchronousQueue
SynchronousQueue是这样 一种阻塞队列,其中每个 put 必须等待一个 take,反之亦然。同步队列没有任何内部容量,甚至连一个队列的容量都没有。
不能在同步队列上进行 peek,因为仅在试图要取得元素时,该元素才存在;
除非另一个线程试图移除某个元素,否则也不能(使用任何方法)添加元素;
也不能迭代队列,因为其中没有元素可用于迭代。队列的头是尝试添加到队列中的首个已排队线程元素; 如果没有已排队线程,则不添加元素并且头为 null。
阻塞队列的常用方法汇总