介面BlockingQueue分析以及實現多個介面時的一點問題
在java併發包中,每種阻塞佇列BlockingQueue都有各自的特性,但是他們都是BlockingQueue的實現,因此分析併發包中的具體實現的BlockingQueue不如先了解BlockingQueue介面各方法的意義,然後具體分析某一個具體BlockingQueue佇列實現,最後推及所有BlockingQueue的特性(本篇本來打算和Queue介面分析作一篇放一塊,但是考慮到add、offer、remove、offer方法區別比較關鍵,因此拆開單獨)。
public interface BlockingQueue<E> extends Queue<E> { /* * 以下add方法和offer方法與介面Queue中的add和offer方法作用一樣,可以參見[Queue介面分析](https://mp.csdn.net/mdeditor/83145869#) * 但是,這裡為什麼還要重複寫一遍呢?大神寫的,不知道為什麼,但這裡體現了介面繼承中的一個特徵, * 即在介面的多繼承時,如果有相同的介面方法,最終JVM會把相同的方法合併成一個 */ boolean add(E e); boolean offer(E e); /* * BlockingQueue中新增了兩個往佇列中新增元素的方法,其目的是保證在多執行緒情況下能將元素新增到 * 佇列中,put方法和這個offer方法的區別在於,一個是死等,一個是有時間限制的等待,但是從方法的定義上, * put和這個offer方法都丟擲了InterruptedException,說明這個等待過程是支援打斷的 * */ void put(E e) throws InterruptedException; boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException; /* * take方法和poll方法新增了等待機制,即等待佇列頭部元素可以被刪除, * 兩者的區別在於,poll方法添加了時間限制,兩者都丟擲了InterruptedException異常 * 這裡有個問題,就是BlockingQueue介面繼承了Queue介面,但Queue介面中沒有丟擲異常,BlockingQueue * 介面中確有丟擲異常,名字一樣,最終以誰為準,最近的,也就是BlockingQueue */ E take() throws InterruptedException; E poll(long timeout, TimeUnit unit) throws InterruptedException; /* * 剩餘的容量,不過用處不大,在多執行緒情況,剩餘容量是永遠在變的 */ int remainingCapacity(); /* * 刪除佇列中的元素o */ boolean remove(Object o); /* * 判斷佇列中是否含有元素o */ public boolean contains(Object o); /* * 以下兩個方法都是批量拽取元素到另一個Collection中方法,BlockingQueue也是一個Collection,因 * 為Queue繼承至Collection */ int drainTo(Collection<? super E> c); int drainTo(Collection<? super E> c, int maxElements); }
結論:
BlockingQueue相對於Queue新增了對待操作成功能力,新增元素和刪除元素,同時支援超時機制,支援打斷,另外支援批量拽取。
但這裡有一個小問題,如果一個介面多繼承兩個不同的介面,而這兩個不同介面各有一個方法名相同但是一個聲明瞭丟擲異常,一個沒有宣告丟擲異常,在實現時,需不需要實現兩個方法?如果不需要,那實現哪個?因為既沒法當作重寫,也沒法當作過載
Interface1.java
public interface Interface1 { void test1(); void test2(); void test() throws Exception ; }
Interface2.java
public interface Interface2 {
void test();
}
ImplementClass.java
public class ImplementClass implements Interface2, Interface1 { @Override public void test1() { } @Override public void test2() { } @Override public void test(){ } }
以上這種方式是可以的。
一旦在ImplementClass類的test方法中加上 throws Exception宣告,將報not compatible with throws clause in Interface2.test(),即不匹配Interface2的test方法了,這個方法沒有宣告拋異常,如果Interface2的test方法加上拋異常的宣告,即Interface2和Interface1的test方法在此時都加上拋異常宣告,即可以。
因此說明,在實現多個介面時,多個介面中有方法名和引數一樣的方法,最好保證拋異常情況一致,如果不一致的化,實現類中實現方法不能寫拋異常宣告,不然會出現匹配錯誤。