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 | 頭部元素 |