LinkedBlockingQueue是一个阻塞的线程安全的队列,底层应该采用链表实现。在入队时有三个api可以实现(put,add,offer),同理出队也对应了三个api(poll、remove、take)。
我们来看下区别:
入队
1.add:add方法在添加元素的时候,若超出了度列的长度会直接抛出异常:
public static void main(String args[]){
try {
LinkedBlockingQueue<String> queue=new LinkedBlockingQueue(2);
queue.add("hello");
queue.add("world");
queue.add("yes");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
//运行结果:
java.lang.IllegalStateException: Queue full
at java.util.AbstractQueue.add(Unknown Source)
- put:对于put方法,若向队尾添加元素的时候发现队列已经满了会发生阻塞一直等待空间,以加入元素。
public static void main(String args[]){
try {
LinkedBlockingQueue<String> queue=new LinkedBlockingQueue(2);
queue.put("hello");
queue.put("world");
queue.put("yes");
System.out.println("yes");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
//运行结果:
//在queue.put("yes")处发生阻塞
3.offer方法在添加元素时,如果发现队列已满无法添加的话,会直接返回false,不会抛异常。
public static void main(String args[]){
try {
LinkedBlockingQueue<String> queue=new LinkedBlockingQueue(2);
boolean bol1=queue.offer("hello");
boolean bol2=queue.offer("world");
boolean bol3=queue.offer("yes");
System.out.println(queue.toString());
System.out.println(bol1);
System.out.println(bol2);
System.out.println(bol3);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
//运行结果:
[hello, world]
true
true
false
出队
add->remove (若队列为空,抛出NoSuchElementException异常)
put->take(如果队列为空执行take,阻塞直到队列种有数据)
offer->poll(如果队列为空执行poll,返回null)
ps
在我最近的项目中,经常使用到的时LinkedBlockingQueue,其出队和入队选用的是offer和poll,我想要的效果是没数据的时候阻塞住,但不能一直阻塞,有时限,所以选用了
E poll(long timeout, TimeUnit unit)
throws InterruptedException;
实际程序如下
String result = queue.poll(1, TimeUnit.MINUTES);
其效果是我可以忍受1分钟之内无数据,线程阻塞,超过1分钟返回null。
且如果我在等待期间被interrupt,抛出InterruptedException异常。
与之对应的是boolean offer(E e, long timeout, TimeUnit unit)
如果在队列满的时候,可以等待设定的时间,超时则返回false
boolean offer(E e, long timeout, TimeUnit unit)和E poll(long timeout, TimeUnit unit)相当于在put->take和offer->poll之间做了折中。
ps:关于队列出队还有两个api,是定义在队列的顶层接口的, E element(),和E peek()。两者都是获得即将出队的元素,但不移除。区别在于如果队列为空,则element会@throws NoSuchElementException,而peek会返回null。