1. 程式人生 > >多執行緒學習之生產者與消費者

多執行緒學習之生產者與消費者

感悟:   生產者和消費者其實就是一個很簡單的一個多執行緒同步的例子,但是我卻花了好多天才能理解。反思下來就是缺乏實踐,這聽起來感覺很簡單的一個道理,但是能做到可就很難了。當初在看這個生產者和消費者例項的時候,看著感覺程式碼能簡單,大致上能理解,但是到了轉天自己卻又寫不出來了,才知道是自己還沒有理解透徹。現在動了一次手實踐一番以後,不說理解透徹,理解個90%還是沒問題的。

基礎準備: notify()是Object類的一個方法,其作用在java-api中說到,喚醒在此物件監視器上等待的單個執行緒,之前一直理解為哪個執行緒呼叫的該方法就喚醒哪個執行緒,這就大錯特錯了。

程式碼實現:

這裡模擬的是生產者生產蘋果,放在公共的盒子上,消費者從公共的盤子上獲取水果。

先寫個公共盤子類PublicBox:

package ThreadProducerAndConsumer;

/**
 * 公共的盒子
 * Created by Curtain on 2018/9/24.
 */
public class PublicBox {
    private int apple = 0;

    //增加蘋果的方法
    public synchronized void increace(){
        while (apple == 5){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        apple++;
        System.out.println("生成蘋果成功!");
        notify();
    }

    public synchronized void decreace(){
        while (apple == 0){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        apple--;
        System.out.println("消費蘋果成功!");
        notify();
    }
}

寫個生產者類Producer:

package ThreadProducerAndConsumer;

/**
 * 生產者(定義10次)
 * Created by Curtain on 2018/9/24.
 */
public class Producer implements Runnable{
    private PublicBox box;

    public Producer(PublicBox box){
        this.box = box;
    }
    @Override
    public void run() {

        //生產10次蘋果
        for (int i = 0; i < 10; i++){
            try {
                System.out.println("pro i:" + i);
                Thread.sleep(30);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            box.increace();
        }
    }
}

寫個消費者類Consumer:

package ThreadProducerAndConsumer;

/**
 * 消費者
 * Created by Curtain on 2018/9/24.
 */
public class Consumer implements Runnable{
    private PublicBox box;

    public Consumer(PublicBox box){
        this.box = box;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++){
            System.out.println("con i:" + i);
            try {
                Thread.sleep(30);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            box.decreace();
        }
    }
}

最後就是測試類:

package ThreadProducerAndConsumer;

/**
 * 生產和和消費者測試
 * Created by Curtain on 2018/9/24.
 */
public class Test01 {
    public static void main(String[] args) {
        PublicBox box = new PublicBox();

        Consumer con = new Consumer(box);
        Producer pro = new Producer(box);

        Thread t1 = new Thread(con);
        Thread t2 = new Thread(pro);

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

執行結果: