JAVA線程sleep()和wait()詳解及實例
sleep
1.sleep是Thread的一個靜態(static)方法。使得Runnable實現的線程也可以使用sleep方法。而且避免了線程之前相互調用sleep()方法,引發死鎖。
2.sleep()執行時需要賦予一個沉睡時間。在沉睡期間(阻塞線程期間),CPU會放棄這個線程,執行其他任務。當沉睡時間到了之後,該線程會自動甦醒,不過此時線程不會立刻被執行,而是要等CPU分配資源,和其他線程進行競爭。
3.此外如果這個線程之前獲取了一個機鎖,在沉睡期間,這個機鎖不會釋放。其他等待這個機鎖的程序,必須等待這個線程醒來,且執行完後才能運行。
sleep相關代碼
public class ThreadTest2 { public static void main(String[] args){ System.out.println("begin our test"); ThreadSleep sleep = new ThreadSleep(); try { Thread thread1 = new Thread(sleep,"路人甲"); Thread thread2 = new Thread(sleep,"路人乙"); thread1.start(); thread2.start(); }catch(Exception e){ e.printStackTrace(); } System.out.println("test is over"); }} class ThreadSleep implements Runnable{ int count = 0; @Override public void run(){ System.out.println(Thread.currentThread().getName() + " say : hello sleep !!"); count(); } public void count(){ while(count < 20) { System.out.println(Thread.currentThread().getName() + " say : count is " + count); try { count++; Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } } }}輸出日誌
begin our testtest is over路人甲say : hello sleep !!路人甲say : count is 0路人乙say : hello sleep !!路人乙say : count is 1路人甲say : count is 2路人乙say : count is 2路人甲say : count is 4路人乙say : count is 4路人甲say : count is 6路人乙say : count is 7路人乙say : count is 8路人甲say : count is 8路人甲say : count is 10路人乙say : count is 10路人乙say : count is 12路人甲say : count is 12路人乙say : count is 14路人甲say : count is 14路人甲say : count is 16路人乙say : count is 16路人甲say : count is 18路人乙say : count is 18
通過日誌可以發現線程甲和線程乙基本是交替執行,但是並不規律,且出現了並發問題。
該情況是由於代碼中設置了睡眠時間為100毫秒,由於count遞增執行速度很快,所以線程差不多是同時睡眠,然後同時甦醒並導致了並發的出現。
接下來要添加synchronize塊,檢查sleep時機鎖是否釋放
public class ThreadTest2 { public static void main(String[] args){ System.out.println("begin our test"); ThreadSleep sleep = new ThreadSleep(); try { Thread thread1 = new Thread(sleep,"路人甲"); Thread thread2 = new Thread(sleep,"路人乙"); thread1.start(); thread2.start(); }catch(Exception e){ e.printStackTrace(); } System.out.println("test is over"); }}class ThreadSleep implements Runnable{ int count = 0; @Override public void run(){ System.out.println(Thread.currentThread().getName() + " say : hello sleep !!"); count(); } public void count(){ while(count < 20) { synchronized (this) { System.out.println(Thread.currentThread().getName() + " say : count is " + count); try { count++; Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } } } }}輸出日誌
begin our test路人甲say : hello sleep !!路人甲say : count is 0test is over路人乙say : hello sleep !!路人甲say : count is 1路人甲say : count is 2路人甲say : count is 3路人甲say : count is 4路人甲say : count is 5路人甲say : count is 6路人甲say : count is 7路人甲say : count is 8路人甲say : count is 9路人甲say : count is 10路人甲say : count is 11路人甲say : count is 12路人甲say : count is 13路人甲say : count is 14路人甲say : count is 15路人甲say : count is 16路人甲say : count is 17路人甲say : count is 18路人甲say : count is 19路人乙say : count is 20
通過日誌可以看出,基本是線程甲在執行,這是因為sleep時,機鎖一直在線程甲上,所以線程乙只能一直等待直到線程甲釋放鎖。
wait
1.wait()是Object類的一個方法。當調用wait()方法時,該線程會進入和該對象相關的等待池中,並釋放它所擁有的機鎖。
2.執行wait()後,必須使用notify()方法或notifyAll()方法或設置等待時間(wait(long time))喚醒在等待線程池中的線程。
3.wait()必須放在synchronized block中,否則會在運行時報“java.lang.IllegalMonitorStateException”異常
wait相關代碼
public class ThreadTest2 { public static void main(String[] args) { System.out.println("begin our test"); ThreadSleep sleep = new ThreadSleep(); try { Thread thread1 = new Thread(sleep, "路人甲"); Thread thread2 = new Thread(sleep, "路人乙"); thread1.start(); thread2.start(); } catch (Exception e) { e.printStackTrace(); } System.out.println("test is over"); }}class ThreadSleep implements Runnable { int count = 0; @Override public void run() { System.out.println(Thread.currentThread().getName() + " say : hello sleep !!"); count(); } public void count() { while (count < 20) { synchronized (this) { System.out.println(Thread.currentThread().getName() + " say : count is " + count); try { count++; this.wait(100); } catch (Exception e) { e.printStackTrace(); } } } }}輸出日誌
begin our test路人甲say : hello sleep !!路人甲say : count is 0test is over路人乙say : hello sleep !!路人乙say : count is 1路人甲say : count is 2路人乙say : count is 3路人甲say : count is 4路人乙say : count is 5路人甲say : count is 6路人乙say : count is 7路人甲say : count is 8路人乙say : count is 9路人甲say : count is 10路人乙say : count is 11路人甲say : count is 12路人乙say : count is 13路人乙say : count is 14路人甲say : count is 15路人乙say : count is 16路人甲say : count is 17路人乙say : count is 18路人甲say : count is 19
通過日誌可以發現在wait的情況下,機鎖會被釋放。
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!