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節》之後的結論)