天天看點

Day49線程池**線程協作

線程的等待與喚醒

  • (1)多個線程可以競争,也可以協作

    賣票屬于競争

    消費與生産屬于協作

    吃貨每吃完一個包子,那麼就要告訴包子鋪生成包子

    包子鋪每生産一個包子,就要通知吃貨去吃

  • (2)相關方法

    void wait():讓目前線程等待,如果沒有人喚醒他,就一直等

    void wait(long timeout):讓目前線程等待,如果到了指定的毫秒值還沒有人喚醒他就自己醒

    void notify() 喚醒一個線程,喚醒的是目前對象鎖下的一個線程

    void notifyAll() 喚醒所有線程,喚醒的是目前對象鎖下面的所有線程

    這些方法一定要放在同步代碼塊中去使用,并且這些方法要通過鎖對象去調用

等待喚醒機制的代碼實作

Day49線程池**線程協作
//倉庫
class CangKu { //當作 鎖對象
    //定義一個變量展現數量
    public int productNum = 0;
}

//生産方
class ProductTask implements Runnable {

    private CangKu cangKu; //共用一個倉庫不能自己建立,由外部傳入

    public ProductTask(CangKu cangKu) {
        this.cangKu = cangKu;
    }

    @Override
    public void run() {
        while (true) {
            //通知與等待必須寫在同步代碼塊中
            synchronized (this.cangKu)/*判斷是否有鎖可用*/ {/*有就進入*/
                if (this.cangKu.productNum == 0) {
                    ++ this.cangKu.productNum;
                    System.out.println("生産了一個産品 " + this.cangKu.productNum);
                    //通知消費者
                    this.cangKu.notify();
                } else {
                    //有貨不用生産,等待通知
                    try {
                        System.out.println("生産方等待中.");
                        this.cangKu.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }//end if
            }//end synchronized 出房間釋放鎖

        }
    }
}

//消費方
class ConsumerTask implements Runnable {
    private CangKu cangKu;

    public ConsumerTask(CangKu cangKu) {
        this.cangKu = cangKu;
    }

    @Override
    public void run() {

        while (true) {
            synchronized (this.cangKu) {
                //判斷 是否為0
                if (this.cangKu.productNum == 0) {
                    try {
                        System.out.println("消費方等待中.");
                        this.cangKu.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    //有貨可以吃
                    -- this.cangKu.productNum ;
                    System.out.println("消費了一個産品:" + this.cangKu.productNum);
                    //通知生産
                    this.cangKu.notify();
                }//end if
            }//end synchronized
        }

    }
}

public class Demo10 {
    public static void main(String[] args) {

        //任務對象
        CangKu cangKu = new CangKu();
        ProductTask productTask = new ProductTask(cangKu);
        ConsumerTask consumerTask = new ConsumerTask(cangKu);
        //定義線程
        ExecutorService pool = Executors.newFixedThreadPool(2);
        pool.submit(productTask);//生産
        pool.submit(consumerTask);//消費
    }
}
//1:邏輯要正确
//2: notify  wait寫在同步代碼塊中,使用同一個對象 倉庫
//3: this.cangku.wait()  this.wait() 前一個使用的是倉庫對象 ,後一個使用的是任務對象