wait時間到或被中斷喚醒時,仍然需要等待獲取鎖。

import java.io.IOException;

public class Demo {

    /**
     * @param args
     * @throws IOException
     * @throws InterruptedException
     * @throws ClassNotFoundException
     */
    public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
        
        T1 t1 = new T1();
        T2 t2 = new T2(t1);
        t1.start();
        t2.start();
        
    }


    static Integer i = 0;

    static class T1 extends Thread {

        public void run() {

            synchronized (i) {
                System.out.println("T1-在syn裏");
                try {
                    i.wait(50L);//驗證表明:wait時間到或被中斷喚醒,不會繼續執行或者跳到catch裏
                                // (因爲根本得不到執行,根本沒法拋出InterruptedException,所以即使catch塊放在syschronized外也一樣 ),
                                //而是還需要等待獲得鎖。
                                //如果wait時間到或被中斷喚醒,而T2還在syn裏,那麼T1還是會等待。
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("結束wait-T1");
                System.out.println("T1-在syn裏");
                try {
                    Thread.sleep(10000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("T1-在syn裏");
            }
            System.out.println("離開syn-T1");

        }
    }
    

    static class T2 extends Thread {

        Thread t1;
        public T2(Thread t1){
            this.t1 = t1;
        }
        
        public void run() {
            synchronized (i) {
                System.out.println("T2-在syn裏");
                try {
                    t1.interrupt();
                    Thread.sleep(10000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("T2-還在syn裏");
            }
            System.out.println("T2-離開syn");

        }
    }
}

 

驗證表明: wait時間到或被中斷喚醒,不一定會繼續執行或者跳到catch裏,而是還需要等待獲得鎖。
               如果wait時間到或被中斷喚醒,而T2還在syn裏,那麼T1還是會等待。

 

另外,Thread.interrupt()喚醒線程之後,其實是設置了Thead的中斷狀態,後續任何時候,當該線程嘗試wait,join,sleep時,中斷狀態都會起作用,使得Thread被中斷,wait/join/sleep方法會拋出中斷異常(wait需要獲取鎖後才能繼續拋出異常)。這點javadoc有說明。

 

 

_____________________________________________________________________________

 

 

 

package com.atell;

import java.io.IOException;

public class Demo {

    public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {

        T1 t1 = new T1();
        T2 t2 = new T2(t1);
        t1.start();
        t2.start();

    }

    static Integer i = 0;

    static class T1 extends Thread {

        public void run() {

            synchronized (i) {
                System.out.println("T1-syn-start");
                try {
                    i.wait();// 可以被notify喚醒,也可以被interrupt喚醒,取決於T2中哪個操作先執行
                } catch (InterruptedException e) {
                    System.out.println("在wait時被中斷");
                }
                try {
                    Thread.sleep(2000L);
                } catch (InterruptedException e) {
                    System.out.println("在sleep時被中斷");
                }
                System.out.println("T1-syn-end");
            }
            System.out.println("離開syn-T1");

        }
    }

    static class T2 extends Thread {

        Thread t1;

        public T2(Thread t1){
            this.t1 = t1;
        }

        public void run() {
            synchronized (i) {
                System.out.println("T2-syn-start");
                //(1)如果先interrupt再notify,那麼i.wait會因爲interrupt而醒過來,notify則不對它起作用(如果此時Monitor的等待隊列有其他線程,則notify必須去喚醒其他線程,不能虛發- Java語言規範17.8.4最後一句明確提到。)。
                //t1.interrupt();
                //i.notify();
                //(2)如果先notify再interrupt,那麼i.wait會因爲notify而醒過來,interrupt則對T1後續的sleep起作用。
                i.notify();
                t1.interrupt();
                System.out.println("T2-syn-end");
            }
            System.out.println("T2-離開syn");

        }
    }
}

 

驗證表明: wait可以被notify喚醒,也可以被interrupt喚醒,取決於哪個操作先執行

(以上是看《Java語言規範17.8節》之後的結論)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章