java生產者消費者專題---談談優化(一)

java生產者消費者專題---談談wait與sleep文中說明了使用wait與sleep方式實現的生產者消費者模式之間的區別,本篇主要談談使用wait方式實現時可能會遇到的一些問題,先貼上代碼:java

public class QueueWithWait<T> extends BlockingQueue<T> {
    private LinkedList<T> queue = new LinkedList<>();
    private final int cacheSize;測試

    public QueueWithWait(int cacheSize) {
        super();
        this.cacheSize = cacheSize;
    }優化

    public T take() {
        synchronized (queue) {
            while(true) {
                if(queue.size()>0) {
                    T obj = queue.poll();
                    queue.notify();
                    return obj;
                }else {
                    try {
                        queue.wait();
                    } catch (InterruptedException e) {
                    }
                }
            }
        }
    }this

    public void put(T obj) {.net

        synchronized (queue) {
            while (true) {
                if (queue.size() < cacheSize) {
                    queue.offer(obj);
                    queue.notify();
                    break;
                } else {
                    try {
                        queue.wait();
                    } catch (InterruptedException e) {
                    }
                }線程

            }
        }blog

    }隊列

}get

代碼中喚醒的操做使用的是notify而不是notifyAll,這樣可能會出現死鎖的狀況,爲了討論方便假設隊列容量只能容納1個元素:假設此時有一個生產者線程和兩個消費者線程,當生產者線程進入wait,一個消費者線程進入wait,若是另外一個消費者線程喚醒的是消費者線程,那麼程序陷入死鎖狀態;但若是隻有一個生產者線程和一個消費者線程就沒問題。當隊列只有一個元素時,能夠按照以上說明寫份測試代碼,而後就能很容易的測出死鎖狀態。it

現說明程序是如何出現生產者線程進入wait,一個消費者線程也進入wait,另外一個消費者線程是活躍狀態的:可能出現的其中一種狀況是假設生產者因爲隊列已滿進入wait狀態,其中一個消費者獲取一個元素後喚醒生產者而後因爲隊列爲空進入wait狀態,另外一個消費者與生產者進行鎖競爭而後消費者因爲隊列爲空進入wait狀態,此時生產者開始生產喚醒其中一個消費者線程而後因爲隊列已滿進入wait狀態,此時就出現了生產者線程進入wait,一個消費者線程也進入wait,另外一個消費者線程是活躍狀態的狀況!

可是將notify該成notifyAll後就不會發生相似這樣的死鎖狀況,儘管不會死鎖可是在效率上依然有優化的空間。

相關文章
相關標籤/搜索