1. 程式人生 > >死鎖|執行緒之間的互動,wait和notify

死鎖|執行緒之間的互動,wait和notify

A執行緒佔用物件蓋倫

B執行緒佔用物件提莫

A試圖佔用提莫,等待B釋放cpu資源

B同理

相互等待,GG

—————————————————————————————————————————————————————————

同樣加血減血

當hurt hp==1時就要停止,當血量加上去了才能繼續hurt

怎麼處理?

t1(關於hurt的執行緒)裡面run覆蓋,while(1)裡面每次hp--,再while(hp==1),continue

將t1的執行緒頻率提高來達到肯定會出現ho==1的情況

可以用set,或者sleep,阻塞時間相對少些就更多的被排程

BUT,這個方法小號cpu太大,效能太低下

這個時候,出現了wait與notify

思路就是,最開始t1佔用,但是hp==1時,wait,這個時候cpu資源釋放出來排程t2的recover加血,加好了notify

就通知等待在this物件上的程序可以醒過來開始工作了

需要注意的時wait()的使用一定在synchronized的塊裡面,因為就是因為這個執行緒獨佔了this其他程序才不能工作

然後wait()讓他讓出cpu,讓出物件,其他執行緒再來,其他執行緒玩夠了,OK,notify,你又繼續

....

這個過程太狗血了..

Hero類:兩個啊方法

 public synchronized

void recover() {
        hp = hp + 1;
        System.out.printf("%s 回血1點,增加血後,%s的血量是%.0f%n", name, name, hp);
        // 通知那些等待在this物件上的執行緒,可以醒過來了,如第20行,等待著的減血執行緒,甦醒過來
        this.notify();
    }
 
    public synchronized
void hurt() {
        if (hp == 1) {
            try {
                // 讓佔有this的減血執行緒,暫時釋放對this的佔有,並等待
                this.wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
 
        hp = hp - 1;
        System.out.printf("%s 減血1點,減少血後,%s的血量是%.0f%n", name, name, hp);
    }

Teetthread類

Thread t1 = new Thread(){
            public void run(){
                while(true){
                       
                    //無需迴圈判斷
//                    while(gareen.hp==1){
//                        continue;
//                    }
                       
                    gareen.hurt();//不等於1直接hurt,等於1進入內層迴圈continue hurt中又讓其wait

                     
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
   
            }
        };
        t1.start();
   
        Thread t2 = new Thread(){
            public void run(){
                while(true){
                    gareen.recover();//t2執行讓他加血,然後notify//起初執行沒那麼快,因為sleep的原因
   
                    try {
                        Thread.sleep(100);

                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
   
            }
        };
        t2.start();
             
    }