Thread類中把線程從running狀態轉化為非runnable狀態有一個方法就是wait方法。wait方法是線程的等待狀態。我們來看看wait方法簡單運用
下面是一個wait方法的代碼
package ThreadTest; /** * thread wait方法詳解 * @author lingfengz * */ public class WaitTest { public static void main(String[] args) { Waitthread wait = new Waitthread(); Thread test1 = new Thread(wait,"線程1"); Thread test2 = new Thread(wait,"線程2"); Thread test3 = new Thread(wait,"線程3"); Thread test4 = new Thread(wait,"線程4"); Thread test5 = new Thread(wait,"線程5"); test1.start(); test2.start(); test3.start(); test4.start(); test5.start(); } } class Waitthread implements Runnable{ private Object lock = new Object(); /** * 實現run方法 */ @Override public void run() { // TODO Auto-generated method stub try{ synchronized(lock){ System.out.println(Thread.currentThread().getName()+"開始了"); lock.wait(); } }catch(InterruptedException e){ e.getStackTrace(); } System.out.println(Thread.currentThread().getName()+"結束了"); } }
從代碼運行的結果可以看出,wait是會釋放鎖的,但是線程下一步操作卻被掛起了。那么我們來看看通過notify();會不會喚醒線程
package ThreadTest; /** * thread wait方法詳解 * @author lingfengz * */ public class WaitTest { public static void main(String[] args) { new Thread(new Wait1()).start(); new Thread(new Wait2()).start(); } public static class Wait1 implements Runnable{ /** * 實現體育老師安排體育課代表進行點名 */ @Override public void run() { // TODO Auto-generated method stub //這個步驟我們可以想象成鎖住的是一節體育課 synchronized (WaitTest.class) { System.out.println("體育老師安排體育委員進行點名"); try { //體育老師在樓下等待,並且交出體育課的鎖。等待體育課代表告訴他點名結束,他開始接管這節體育課 WaitTest.class.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("體育老師得到點名的結果開始上課"); } } } public static class Wait2 implements Runnable{ /** * 實現體育課代表進行隊列點名 */ @Override public void run() { // TODO Auto-generated method stub synchronized (WaitTest.class) { System.out.println("體育委員進行點名"); try { //點名需要花費的時間 Thread.sleep(1000L); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("體育委員點名結束"); //通知體育老師點名結束了 WaitTest.class.notify(); System.out.println("體育課代表帶人去操場"); } } } } 運行結果: 體育老師安排體育委員進行點名 體育委員進行點名 體育委員點名結束 體育課代表帶人去操場 體育老師得到點名的結果開始上課
我們從上面的代碼可以看到test1這個對象鎖.wait后。Waitthread線程中notify();進行了喚醒。線程被喚醒,如果我們把notify();給注銷掉會有什么樣的結果呢.
package ThreadTest; /** * thread wait方法詳解 * @author lingfengz * */ public class WaitTest { public static void main(String[] args) { new Thread(new Wait1()).start(); new Thread(new Wait2()).start(); } public static class Wait1 implements Runnable{ /** * 實現體育老師安排體育課代表進行點名 */ @Override public void run() { // TODO Auto-generated method stub //這個步驟我們可以想象成鎖住的是一節體育課 synchronized (WaitTest.class) { System.out.println("體育老師安排體育委員進行點名"); try { //體育老師在樓下等待,並且交出體育課的鎖。等待體育課代表告訴他點名結束,他開始接管這節體育課 WaitTest.class.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("體育老師得到點名的結果開始上課"); } } } public static class Wait2 implements Runnable{ /** * 實現體育課代表進行隊列點名 */ @Override public void run() { // TODO Auto-generated method stub synchronized (WaitTest.class) { System.out.println("體育委員進行點名"); try { //點名需要花費的時間 Thread.sleep(1000L); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("體育委員點名結束"); //通知體育老師點名結束了 //WaitTest.class.notify(); System.out.println("體育課代表帶人去操場"); } } } } 運行結果 體育老師安排體育委員進行點名 體育委員進行點名 體育委員點名結束 體育課代表帶人去操場
從上面可以看到,體育委員沒有通知體育老師點名結束(notify();),那么體育老師還在等待體育委員的通知。但是體育委員已經帶人去操場了。這節體育課,如果體育委員不通知體育老師點名結束的,體育老師就不會來上課了。
從上面我們可以看到wait();方法是無限等待。那么我們生活中體育老師中,體育委員忘了通知體育老師,體育老師就不來上課了?答案肯定是體育老師還是會過來,但是肯定有一段等待的時間
那么我們試試給wait的其他方法。給wait一個時間的參數
package ThreadTest; import java.text.SimpleDateFormat; import java.util.Date; /** * thread wait方法詳解 * @author lingfengz * */ public class WaitTest { public static void main(String[] args) { new Thread(new Wait1()).start(); new Thread(new Wait2()).start(); } public static class Wait1 implements Runnable{ /** * 實現體育老師安排體育課代表進行點名 */ @Override public void run() { // TODO Auto-generated method stub //這個步驟我們可以想象成鎖住的是一節體育課 synchronized (WaitTest.class) { System.out.println("體育老師安排體育委員進行點名"); try { //體育老師開始看手表,准備上課 System.out.println("體育老師開始等待時間:"+new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss:SSS").format(new Date())); //體育老師在樓下等待,並且交出體育課的鎖。等待體育課代表告訴他點名結束,他開始接管這節體育課。如果1000L之后體育課代表還不通知他,他將直接去操場上課 WaitTest.class.wait(1000L); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("體育老師結束等待時間:"+new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss:SSS").format(new Date())); //System.out.println("體育老師得到點名的結果開始上課"); System.out.println("體育老師去操場開始上課"); } } } public static class Wait2 implements Runnable{ /** * 實現體育課代表進行隊列點名 */ @Override public void run() { // TODO Auto-generated method stub synchronized (WaitTest.class) { System.out.println("體育委員進行點名"); try { //點名需要花費的時間 Thread.sleep(1000L); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("體育委員點名結束"); //通知體育老師點名結束了 //WaitTest.class.notify(); System.out.println("體育課代表帶人去操場"); } } } } 運行結果: 體育老師安排體育委員進行點名 體育老師開始等待時間:2019/03/18-13:01:08:995 體育委員進行點名 體育委員點名結束 體育課代表帶人去操場 體育老師結束等待時間:2019/03/18-13:01:09:999 體育老師去操場開始上課
從上面的執行結果來看wait,如果有時間參數的話,在時間參數之內被沒被喚醒的話,在時間到達之后他可以自己喚醒。
所以我們得出結論:wait的幾種情況
首先wait是會放棄鎖,進入等待區。第二wait可以被其他線程所喚醒。
第三如果wait有時間參數,就算沒有其他線程喚醒,他也會自動喚醒。