接口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方法在此时都加上抛异常声明,即可以。

因此说明,在实现多个接口时,多个接口中有方法名和参数一样的方法,最好保证抛异常情况一致,如果不一致的化,实现类中实现方法不能写抛异常声明,不然会出现匹配错误。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章