Lock && Condition_實現有界緩存

Lock && Condition_實現有界緩存java

Lock是一種廣義的內置鎖,Condition也是一種廣義的內置條件隊列緩存

內置條件隊列存在一些缺陷。每一個內置鎖都只能有一個相關的條件隊列,於是多個線程可能在同一個條件隊列上等待不一樣的條件謂詞,而且在最多見的加鎖模式下公開條件隊列對象。併發

這些因素都使得沒法知足在使用notifyAll時全部等待線程爲同一類型的需求。若是想編寫一個帶有多個條件謂詞的併發對象,或者想得到除了條件隊列可見性的更多控制權,就能夠使用顯示的Lock和Condition而不是內置鎖和內置條件隊列,這是一種更靈活的選擇。ide

Lock比內置鎖提供了更爲豐富的功能,Condition一樣比內置條件隊列提供了更豐富的功能:在每一個鎖上可能存在多個等待、條件等待能夠是可中斷的、基於時限的等待,以及公平的或非公平的隊列操做。this

與內置條件隊列不一樣的是,對於每一個Lock,能夠有任意數量的Condition對象。Condition對象繼承了相關的Lock對象的公平性,對於公平的鎖,線程會依照FIFO順序從Condition.await中釋放。spa

下面這段程序給出了有界緩存的另外一種實現,即‍使用兩個Condition,分別爲notFull和notEmpty‍,用於表示」非滿「和」非空「兩個條件謂詞。當緩存爲空時,take將阻塞並等待notEmpty,此時put向notEmpty發送信號,能夠解除任何在take中阻塞的線程。線程

 

使用顯示條件變量的有界緩存

package sync;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created with IntelliJ IDEA.
 * User: ASUS
 * Date: 14-9-1
 * Time: 下午9:20
 * To change this template use File | Settings | File Templates.
 */
public class ConditionBoundedBuffer<T> {

    protected final Lock lock = new ReentrantLock();

    //條件謂詞:notFull
    private final Condition notFull = lock.newCondition();
    //條件謂詞:notEmpty
    private final Condition notEmpty = lock.newCondition();
    private final T[] items;
    private int tail, head, count;

    protected ConditionBoundedBuffer(int size) {
        items = (T[]) new Object[size];
    }

    /**
     * 阻塞並直到notFull
     *
     * @param x
     * @throws InterruptedException
     */
    public void put(T x) throws InterruptedException {
        lock.lock();
        try {
            while (count == items.length) {
                // 阻塞,等待非滿條件
                System.out.println("not full await");
                notFull.await();
            }

            items[tail] = x;
            if (++tail == items.length) {
                tail = 0;
            }

            ++count;
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }


    /**
     * 阻塞並直到notEmpty
     *
     * @return
     * @throws InterruptedException
     */
    public T take() throws InterruptedException {
        lock.lock();
        try {
            while (count == 0) {
                // 阻塞,等待非空條件
                System.out.println("not empty await");
                notEmpty.await(); //如今有界緩存爲空,要等到非空狀態才能取出元素
            }

            T x = items[head];
            items[head] = null;
            if (++head == items.length) {
                head = 0;
            }
            --count;
            notFull.signal(); //元素已被取出,通知非滿狀態
            return x;
        } finally {
            lock.unlock();
        }
    }

    public static void main(String args[]) {

        final ConditionBoundedBuffer buffer = new ConditionBoundedBuffer(10);

        //線程t2打印緩存中的消息
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        System.out.println(buffer.take());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        //線程t1放入緩存消息
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    try {
                        buffer.put(new String("sadsasd"));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        t2.start();
        t1.start();
    }
}

============END============code

相關文章
相關標籤/搜索