Thread.sleep()和Object.wait()的區(qū)別
首先,我們先來(lái)看看Thread.sleep()和Object.wait()的區(qū)別,這是一個(gè)爛大街的題目了,大家應(yīng)該都能說(shuō)上來(lái)兩點(diǎn)。
Thread.sleep()不會(huì)釋放占有的鎖,Object.wait()會(huì)釋放占有的鎖;Thread.sleep()必須傳入時(shí)間,Object.wait()可傳可不傳,不傳表示一直阻塞下去;Thread.sleep()到時(shí)間了會(huì)自動(dòng)喚醒,然后繼續(xù)執(zhí)行;Object.wait()不帶時(shí)間的,需要另一個(gè)線程使用Object.notify()喚醒; Object.wait()帶時(shí)間的,假如沒(méi)有被notify,到時(shí)間了會(huì)自動(dòng)喚醒,這時(shí)又分好兩種情況,一是立即獲取到了鎖,線程自然會(huì)繼續(xù)執(zhí)行;二是沒(méi)有立即獲取鎖,線程進(jìn)入同步隊(duì)列等待獲取鎖;
其實(shí),他們倆最大的區(qū)別就是Thread.sleep()不會(huì)釋放鎖資源,Object.wait()會(huì)釋放鎖資源。
Object.wait()和Condition.await()的區(qū)別
Object.wait()和Condition.await()的原理是基本一致的,不同的是Condition.await()底層是調(diào)用LockSupport.park()來(lái)實(shí)現(xiàn)阻塞當(dāng)前線程的。
實(shí)際上,它在阻塞當(dāng)前線程之前還干了兩件事,一是把當(dāng)前線程添加到條件隊(duì)列中,二是“完全”釋放鎖,也就是讓state狀態(tài)變量變?yōu)?,然后才是調(diào)用LockSupport.park()阻塞當(dāng)前線程。
Thread.sleep()和LockSupport.park()的區(qū)別
LockSupport.park()還有幾個(gè)兄弟方法——parkNanos()、parkUtil()等,我們這里說(shuō)的park()方法統(tǒng)稱這一類方法。
從功能上來(lái)說(shuō),Thread.sleep()和LockSupport.park()方法類似,都是阻塞當(dāng)前線程的執(zhí)行,且都不會(huì)釋放當(dāng)前線程占有的鎖資源; Thread.sleep()沒(méi)法從外部喚醒,只能自己醒過(guò)來(lái); LockSupport.park()方法可以被另一個(gè)線程調(diào)用LockSupport.unpark()方法喚醒;Thread.sleep()方法聲明上拋出了InterruptedException中斷異常,所以調(diào)用者需要捕獲這個(gè)異常或者再拋出;LockSupport.park()方法不需要捕獲中斷異常;Thread.sleep()本身就是一個(gè)native方法;LockSupport.park()底層是調(diào)用的Unsafe的native方法;
Object.wait()和LockSupport.park()的區(qū)別
二者都會(huì)阻塞當(dāng)前線程的運(yùn)行,他們有什么區(qū)別呢? 經(jīng)過(guò)上面的分析相信你一定很清楚了,真的嗎? 往下看!
Object.wait()方法需要在synchronized塊中執(zhí)行; LockSupport.park()可以在任意地方執(zhí)行;Object.wait()方法聲明拋出了中斷異常,調(diào)用者需要捕獲或者再拋出;LockSupport.park()不需要捕獲中斷異常;Object.wait()不帶超時(shí)的,需要另一個(gè)線程執(zhí)行notify()來(lái)喚醒,但不一定繼續(xù)執(zhí)行后續(xù)內(nèi)容; LockSupport.park()不帶超時(shí)的,需要另一個(gè)線程執(zhí)行unpark()來(lái)喚醒,一定會(huì)繼續(xù)執(zhí)行后續(xù)內(nèi)容;
park()/unpark()底層的原理是“二元信號(hào)量”,你可以把它相像成只有一個(gè)許可證的Semaphore,只不過(guò)這個(gè)信號(hào)量在重復(fù)執(zhí)行unpark()的時(shí)候也不會(huì)再增加許可證,最多只有一個(gè)許可證。