前言:本文解決的問題
- wait() await() sleep()這三個方法有申請區別
在找工作的各種筆試題目中,經常看到wait()、sleep()還有await(),功能都很相似,到底有什么區別?什么時候該用哪一種方法
1. wait() VS sleep()
wait和sleep的比較可以說是高頻面試題。方法原型分別為:
public final native void wait(long timeout) throws InterruptedException;
public static native void sleep(long millis) throws InterruptedException;
同:
- 都是線程同步時會用到的方法,使當前線程暫停運行,把運行機會交給其它線程。
- 如果任何線程在等待期間被中斷都會拋出InterruptedException
- 都是native方法
異:
- 所在類不同,wait()是Object超類中的方法;而sleep()是線程Thread類中的方法
- 關鍵點是對鎖的保持不同,wait會釋放鎖;而sleep()並不釋放鎖
- 喚醒方法不完全相同,wait依靠notify或者notifyAll、中斷發生、或者到達指定時間來喚醒;而sleep()則是到達指定的時間后被喚醒。
- 使用的位置不同,wait只能用在同步代碼塊中,而sleep用在任何位置。
2. wait() VS await()
這兩個長得很像。await()的實現比較復雜。
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
先說下來源,await是ConditionObject類里面的方法,ConditionObject實現了Condition接口;而ReentrantLock里面默認有實現newCondition()方法,新建一個條件對象。該方法就是用在ReentrantLock中根據條件來設置等待。喚醒方法也是由專門的Signal()或者Signal()來執行。另外await會導致當前線程被阻塞,會放棄鎖,這點和wait是一樣的。
由於所在的超類不同使用場景也不同,wait一般用於Synchronized中,而await只能用於ReentrantLock鎖中,具體如下
wait()
synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout);
... // Perform action appropriate to condition
}
await()主要見上文。
3 notify signal
順便說下這二者的區別,notify使用來喚醒使用wait的線程;而signal是用來喚醒await線程。
