BlockingQueue在异步处理的时候经常用到它的存放和取出数据的操作,但是如存放也有add、offer等多个方法,这些方法有什么区别,这边用LinkedBlockingQueue作为实现测试一下。
存放
先上方法:
boolean add(E e);
boolean offer(E e);
void put(E e) throws InterruptedException;
boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException;
从方法的声明可以看出点端倪,put方法是阻塞的,如果这个队列满了,那么它会一直阻塞等待,直到队列出现空位可以放元素,或者是线程被中断。
至于offer()和add(),看下面的代码:
BlockingQueue queue = new LinkedBlockingQueue(2);
queue.offer(1);
System.out.println(queue.size());
queue.offer(2);
System.out.println(queue.size());
queue.offer(3);
System.out.println(queue.size());
queue.add(4);
System.out.println(queue.size());
输出:
1
2
2
Exception in thread "main" java.lang.IllegalStateException: Queue full
可以看出来,offer是一个投资人,就是试一下能不能在队列中放一个元素,尝试的时间可以设定,但是发现不行以后会马上终止,并且返回true或者false。而add是家暴,可以理解为强行加入元素,但是不能加入的时候(比如队列有长度限制并且已经达到长度),直接粗暴的抛出IllegalStateException进行警告。
取出
先上方法
E take() throws InterruptedException;
E poll(long timeout, TimeUnit unit)
throws InterruptedException;
然后举个例子
BlockingQueue queue = new LinkedBlockingQueue(2);
queue.offer(1);
System.out.println(queue.size());
queue.offer(2);
System.out.println(queue.size());
queue.poll(1, TimeUnit.SECONDS);
System.out.println(queue.size());
queue.poll(1, TimeUnit.SECONDS);
System.out.println(queue.size());
queue.poll(1, TimeUnit.SECONDS);
System.out.println(queue.size());
queue.take();
System.out.println(queue.size());
输出:
1
2
1
0
0
(线程一直等待...)
可以看出来,poll方法也是投资人的方式,可以设定时间,然后在无法取出元素的时候果断返回false。而take方法就是一直阻塞等待有元素可以,或者线程被中断。
总结
以上是BlockingQueue中用到的关于存放和取出方法的举例,在LinkedBlockingQueue实现中,还有peek之类的方法,做一个总结放在下面。
方法 | 效果 | 是否阻塞 | 是否抛出异常 | 返回 |
---|---|---|---|---|
boolean add(E e) | 添加 | 否 | 队列满导致添加失败时抛出IllegalStateException | true/false |
boolean offer(E e) | 添加 | 否 | 否 | true/false |
boolean offer(E e, long timeout, TimeUnit unit) | 添加 | 是(指定时间) | 否 | true/false |
void put(E e) | 添加 | 是(无期限) | 阻塞线程中断时抛出InterruptedException | true/false |
E take() | 取出 | 是(无期限) | 阻塞线程中断时抛出InterruptedException | 头部元素 |
E poll(long timeout, TimeUnit unit) | 取出 | 是(指定时间) | 阻塞线程中断时抛出InterruptedException | 头部元素/null |
E remove() | 取出 | 否 | 队列为空时抛出NoSuchElementException | 头部元素 |
E peek() | 查看 | 否 | 否 | 头部元素/null |
E element() | 查看 | 否 | 队列为空时抛出NoSuchElementException | 头部元素 |