麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發設計 > 正文

《java.util.concurrent 包源碼閱讀》07 LinkedBlockingQueue

2019-11-14 20:50:19
字體:
來源:轉載
供稿:網友
java.util.concurrent 包源碼閱讀》07 LinkedBlockingQueue

這篇文章來說說稍微復雜一些的LinkedBlockingQueue。LinkedBlockingQueue使用一個鏈表來實現,會有一個head和tail分別指向隊列的開始和隊列的結尾。因此LinkedBlockingQueue會有兩把鎖,分別控制這兩個元素,這樣在添加元素和拿走元素的時候就不會有鎖的沖突,因此取走元素操作的是head,而添加元素操作的是tail。

老規矩先看offer方法和poll方法

    public boolean offer(E e) {        if (e == null) throw new NullPointerException();        final AtomicInteger count = this.count;        if (count.get() == capacity)            return false;        int c = -1;        Node<E> node = new Node(e);        final ReentrantLock putLock = this.putLock;        putLock.lock();        try {            if (count.get() < capacity) {                enqueue(node);                c = count.getAndIncrement();                if (c + 1 < capacity)                    notFull.signal();            }        } finally {            putLock.unlock();        }        if (c == 0)            signalNotEmpty();        return c >= 0;    }

可以看到offer方法在添加元素時候僅僅涉及到putLock,但是還是會需要takeLock,看看signalNotEmpty代碼就知道。而poll方法拿走元素的時候涉及到takeLock,也是會需要putLock。參見signalNotFull()。關于signalNotEmpty會在后面講阻塞的時候講到。

    public E poll() {        final AtomicInteger count = this.count;        if (count.get() == 0)            return null;        E x = null;        int c = -1;        final ReentrantLock takeLock = this.takeLock;        takeLock.lock();        try {            if (count.get() > 0) {                x = dequeue();                c = count.getAndDecrement();                if (c > 1)                    notEmpty.signal();            }        } finally {            takeLock.unlock();        }        if (c == capacity)            signalNotFull();        return x;    }

這里順便說說隊列長度的count,因為有兩把鎖存在,所以如果還是像ArrayBlockingQueue一樣使用基本類型的count的話會同時用到兩把鎖,這樣就會很復雜,因此直接使用原子數據類型AtomicInteger來操作count。

接下來談談阻塞的問題,一個BlockingQueue會有兩個Condition:notFull和notEmpty,LinkedBlockingQueue會有兩把鎖,因此這兩個Condition肯定是由這兩個鎖分別創建的,takeLock創建notEmpty,putLock創建notFull。

    /** Lock held by take, poll, etc */    PRivate final ReentrantLock takeLock = new ReentrantLock();    /** Wait queue for waiting takes */    private final Condition notEmpty = takeLock.newCondition();    /** Lock held by put, offer, etc */    private final ReentrantLock putLock = new ReentrantLock();    /** Wait queue for waiting puts */    private final Condition notFull = putLock.newCondition();

接下來看看put方法:

    public void put(E e) throws InterruptedException {        if (e == null) throw new NullPointerException();        // Note: convention in all put/take/etc is to preset local var        // holding count negative to indicate failure unless set.        int c = -1;        Node<E> node = new Node(e);        final ReentrantLock putLock = this.putLock;        final AtomicInteger count = this.count;        putLock.lockInterruptibly();        try {            /*             * Note that count is used in wait guard even though it is             * not protected by lock. This works because count can             * only decrease at this point (all other puts are shut             * out by lock), and we (or some other waiting put) are             * signalled if it ever changes from capacity. Similarly             * for all other uses of count in other wait guards.             */            while (count.get() == capacity) {                notFull.await();            }            enqueue(node);            c = count.getAndIncrement();            if (c + 1 < capacity)                notFull.signal();        } finally {            putLock.unlock();        }        if (c == 0)            signalNotEmpty();    }

其實大體邏輯和ArrayBlockingQueue差不多,也會需要通知notEmpty條件,因為notEmpty條件屬于takeLock,而調用signal方法需要獲取Lock,因此put方法也是用到了另外一個鎖:takeLock。這里有一點會不同,按照道理來說put方法是不需要通知notFull條件的,是由由拿走元素的操作來通知的,但是notFull條件屬于putLock,而拿走元素時,是用了takeLock,因此這里put方法在擁有putLock的情況通知notFull條件,會讓其他添加元素的方法避免過長時間的等待。同理對于take方法來說也通知notEmpty條件。

    public E take() throws InterruptedException {        E x;        int c = -1;        final AtomicInteger count = this.count;        final ReentrantLock takeLock = this.takeLock;        takeLock.lockInterruptibly();        try {            while (count.get() == 0) {                notEmpty.await();            }            x = dequeue();            c = count.getAndDecrement();            if (c > 1)                notEmpty.signal();        } finally {            takeLock.unlock();        }        if (c == capacity)            signalNotFull();        return x;    }

最后說說remove和contains方法,因為需要操作整個鏈表,因此需要同時擁有兩個鎖才能操作。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 亚洲aⅴ免费在线观看 | 国内免费视频成人精品 | 国产一级在线观看视频 | 黄色毛片观看 | 天天夜夜草 | 海外中文字幕在线观看 | 久久日韩在线 | 精品一区二区三区网站 | 欧美成视频在线观看 | 激情大乳女做爰办公室韩国 | 国产黄色毛片 | 成人免费毛片一 | 欧美国产日韩在线观看成人 | www.99热视频 | 中文字幕在线观看精品 | 久色视频网站 | 久久久久久久久久久av | 免费黄色一级网站 | 亚洲午夜久久久久 | 干色视频 | 免费看a级片 | 久久久av亚洲男天堂 | 黄色片免费在线播放 | 中国女人内谢69xxxx天美 | 婷婷久久网 | 三人弄娇妻高潮3p视频 | 精品国产一区二区三区久久久蜜月 | 日韩视频一区二区在线观看 | caoporn国产一区二区 | 蜜桃av鲁一鲁一鲁一鲁 | 免费一级a毛片免费观看 | 久草高清视频 | 久久久国产精品成人免费 | 中文字幕精品亚洲 | 黄色一级视频 | 成人免费观看在线 | 成年人黄色免费电影 | 毛片国产 | 日夜操天天干 | 成人在线观看免费高清 | 免费观看一级黄色片 |