Thread Wait

      在〈Thread Wait〉中尚無留言

情境

要怎麼解釋wait的作用, 蠻難的. 這主題讓我想破了頭, 該用什麼例子讓大家輕易的明白呢.
好啦, 還是用我們的經典例子~~神奇寶貝來說明吧.

我的公司專門生產皮卡丘的玩偶. 公司每秒鐘只能生產一隻皮卡丘.  但因為賣的太好了,  很多的Vendor(販賣商, A店, B店, C店)都要來搶貨.

Vendor當然是到我公司的倉庫搶, 倉庫只有一個出貨窗口. 大家一個一個來, 有貨就通知ABC店來搶. 搶得到就拿去賣. 搶不到就只能跟買主說缺貨啦.

主程式

class Factory是我的公司, 專門製造皮卡丘玩偶.
Thread t1, t2, t3, 是我的販賣商, 三不五時都有客人要來買皮卡丘.

而我的公司有inventory(倉庫), getGoods(取貨)

class Pikachu則是我公司的產品.

public class JavaApp{
    public static void main(String[] args) {
        Factory factory=new Factory();
        factory.start();
        Vendor vendor=new Vendor(factory);
        Thread t1=new Thread(vendor, "A店");
        Thread t2=new Thread(vendor, "B店");
        Thread t3=new Thread(vendor, "C店");
        t1.start();
        t2.start();
        t3.start();
    }
}
class Vendor implements Runnable{
    Factory factory;
    public Vendor(Factory factory){
        this.factory=factory;
    }
    @Override
    public void run() {
        while(true){
            synchronized(factory){
                if(factory.warehouse.size()==0){
                    try {
                        //請注意, 此處是擁有factory物件鎖的執行緒到blocked區, 並不是warehouse去等待區
                        factory.wait();
                    } catch (InterruptedException ex) {}
                }
                if(factory.warehouse.size()!=0){
                    System.out.printf("%s:%s\n", Thread.currentThread().getName(), factory.warehouse.remove(0).product);
                }
            }
         }
    }
}
class Factory extends Thread{
    //倉庫
    Listwarehouse=new ArrayList<>();
    
    //生產線, 每一秒生產一隻皮卡丘
    public void run(){
        while(true){
            synchronized(this){
                warehouse.add(new Pikachu());
                this.notify();
            }
            try {
                Thread.sleep(500);
            } catch (InterruptedException ex) {}
        }
    }
}

//商品名稱 -- 皮卡丘
class Pikachu{
    public static int sn=1;
    public String product="";
    public Pikachu(){
        String tmp="";
        for (int i=0;i<10;i++){
            tmp+=(char)(Math.random()*26+65);
        }
        product=String.format("序號:%05d, 名稱 : %s", sn++, tmp);
    }
}

結果如下

C店:序號:00001, 名稱 : ONFNSMTVIB
C店:序號:00002, 名稱 : PVHOJRJETR
B店:序號:00003, 名稱 : AQJXNUECMQ
A店:序號:00004, 名稱 : OVSMKAWBDI
C店:序號:00005, 名稱 : COYFIWGHYM
B店:序號:00006, 名稱 : AAKIOGSNOE
A店:序號:00007, 名稱 : YSDWJIQMFT
C店:序號:00008, 名稱 : BGONCGANWW
B店:序號:00009, 名稱 : MUPZVJINAY
A店:序號:00010, 名稱 : CZMVMVBYYM
C店:序號:00011, 名稱 : DCKIVZHKSU

重點

wait, 是讓目前執行緒, 在擁有某物件鎖且進入synchronized區塊後, 調用此物件的wait方法, 然後將目前執行緒推入等待區暫緩執行.

所以要使用wait方法, 一定要在synchronized的區塊會方法中. 執行緒經由wait推入blocked區後, 會交出物件鎖, 供其他執行緒使用.

其他執行緒取得物件鎖(進入synchronized)後, 可以使用notify通知等待區的一個執行緒復活. 或使用notifyAll讓所有執行緒復活.

請注意,  factory.wait(); 是擁有factory物件鎖的執行緒到blocked區, 並不是factory去等待區.

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *