(二)線程同步_2---在同步代碼塊中使用條件

在同步代碼塊中使用條件(Using condition in synchronized code)

在併發編程中,生產者-消費者(producer-consumer)是一個經典的問題;一個數據緩衝區,一個或多個生產者向這個緩衝區寫數據,一個或多個消費者從這個緩衝區中讀數據,緩衝區做爲線程共享資源,須要採用同步機制控制,好比使用synchronized關鍵字,可是咱們還須要更多的限制條件,好比當緩衝區滿時就不能在寫入數據,當緩衝區空時就不能在讀取數據;java

對於這種狀況,Javaz提供了wait() , notify()和notifyAll() 方法,這幾個方法都是Object對象的方法;一個線程只能在synchronized代碼塊中調用wait()方法,若是在synchronized代碼塊以外調用wait()方法,JVM將會拋出一個IllegalMonitorStateException異常;當一個線程調用wait()方法時,這個線程將會被休眠(sleep)而且釋放對以前鎖定的對象中的同步代碼塊,此時其它線程將有機會執行這個對象的同步代碼塊;當要喚醒這個線城時,能夠調用被鎖定對象的notify()或notifyAll()方法;編程

下面的實例中將會展現這幾個方法是如何使用的;併發

動手實現

1. 建立一個EventStorage類ide

public class EventStorage {
    private int maxSize;
    private LinkedList<Date> storage;

    public EventStorage(){
        maxSize=10;
        storage = new LinkedList<>();
    }

    public synchronized void set() {
        while (storage.size() == maxSize) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        storage.offer(new Date());
        System.out.printf("Set:%d\n",storage.size());
        notifyAll();
    }

    public synchronized void get() {
        while (storage.size() == 0) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.printf("Get:%d: %s\n", storage.size(), storage.poll());
        notifyAll();
    }
}
2.分別建立生產者和消費者

public class Consumer implements Runnable {
    private EventStorage eventStorage;

    public Consumer(EventStorage eventStorage) {
        this.eventStorage = eventStorage;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            eventStorage.get();
        }
    }
}

public class Producer implements Runnable {
    private EventStorage eventStorage;

    public Producer(EventStorage eventStorage) {
        this.eventStorage = eventStorage;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            eventStorage.set();
        }
    }
}

3.Main

public class Main {
    public static void main(String[] args) {
        EventStorage storage=new EventStorage();

        Producer producer=new Producer(storage);
        Thread thread1=new Thread(producer);

        Consumer consumer=new Consumer(storage);
        Thread thread2=new Thread(consumer);

        thread2.start();
        thread1.start();
    }
}

要點

觀察運行結果,會發現eventstorage 至多會有10個事件
相關文章
相關標籤/搜索