wait方法是Object里面的一個native方法,而sleep是Thread里面的方法,下面分別來看兩個方法的源碼:
/**
* Causes the current thread to wait until another thread invokes the
* {@link java.lang.Object#notify()} method or the
* {@link java.lang.Object#notifyAll()} method for this object.
* In other words, this method behaves exactly as if it simply
* performs the call {@code wait(0)}.
* <p>
* The current thread must own this object's monitor. The thread
* releases ownership of this monitor and waits until another thread
* notifies threads waiting on this object's monitor to wake up
* either through a call to the {@code notify} method or the
* {@code notifyAll} method. The thread then waits until it can
* re-obtain ownership of the monitor and resumes execution.
* This method should only be called by a thread that is the owner
* of this object's monitor. See the {@code notify} method for a
* description of the ways in which a thread can become the owner of
* a monitor.
*This method should only be called by a thread that is the owner
* of this object's monitor. See the {@code notify} method for a
* description of the ways in which a thread can become the owner of
* a monitor.
*
**/
public final native void wait() throws InterruptedException;
從官方的注釋可以知道,當(dāng)前線程對要持有當(dāng)前對象的資源鎖,并且當(dāng)前線程會釋放鎖。
而且要調(diào)用notify喚醒wait的線程時,必須先持有對象的資源鎖,從這里可以知道,不管是調(diào)用wait或者
notify,都要持有同一個對象的鎖。
public void funcWait() {
synchronized(obj) {
obj.wait()
}
}
public void funcNotify() {
synchronized(obj) {
obj.notify()
}
}
Sleep
/**
* Causes the currently executing thread to sleep (temporarily cease
* execution) for the specified number of milliseconds, subject to
* the precision and accuracy of system timers and schedulers. The thread
* does not lose ownership of any monitors.
*
* @param millis
* the length of time to sleep in milliseconds
*
* @throws IllegalArgumentException
* if the value of {@code millis} is negative
*
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* <i>interrupted status</i> of the current thread is
* cleared when this exception is thrown.
*/
public static void sleep(long millis) throws InterruptedException {
Thread.sleep(millis, 0);
}
@FastNative
private static native void sleep(Object lock, long millis, int nanos)
throws InterruptedException;
發(fā)現(xiàn)官方注釋上面,sleep的時候是沒有 釋放資源鎖的。這就是跟wait最大的區(qū)別.
下面寫對應(yīng)例子驗證:
private Object waitObj = new Object();
public void funForWait(int id) {
synchronized(waitObj) {
Log.e("@@@", "wait begin " + id);
try {
waitObj.wait();
}catch (Exception e) {
e.printStackTrace();
}
Log.e("@@@", "wait end : " + id);
}
}
public void funForSleep(int id) {
synchronized(waitObj) {
Log.e("@@@", "sleep begin : " + id);
try {
Thread.sleep(2000);
}catch (Exception e) {
e.printStackTrace();
}
Log.e("@@@", "sleep end : " + id);
}
}
for (int i = 0; i < 4; i++) {
final int id = i;
new Thread(new Runnable() {
@Override
public void run() {
funForWait(id);
}
}).start();
}
上面測試wait和sleep分別輸出入下:
wait
E/@@@: wait begin 0
E/@@@: wait begin 1
E/@@@: wait begin 2
E/@@@: wait begin 3
sleep:
E/@@@: sleep begin : 0
E/@@@: sleep end : 0
E/@@@: sleep begin : 1
E/@@@: sleep end : 1
E/@@@: sleep begin : 3
E/@@@: sleep end : 3
E/@@@: sleep begin : 2
E/@@@: sleep end : 2
從上面的輸出可以看出,當(dāng)調(diào)用wait的時候,其他線程是可以繼續(xù)調(diào)用funForwait方法并且訪問
Log.e("@@@", "wait begin " + id);
而調(diào)用sleep的則不行,從這里可以看出,wait的時候,線程是釋放了對Object的鎖,而sleep卻沒有,所以
Log.e("@@@", "sleep begin : " + id);
這段代碼當(dāng)?shù)谝粋€線程進(jìn)入sleep的時候,其他線程被掛起并且訪問不了這段代碼,原因是因為當(dāng)前線程還是持有Object資源鎖。
如果想要中斷當(dāng)前正在掛起等待的線程,可以調(diào)用
/**
* <p> If this thread is blocked in an invocation of the {@link
* Object#wait() wait()}, {@link Object#wait(long) wait(long)}, or {@link
* Object#wait(long, int) wait(long, int)} methods of the {@link Object}
* class, or of the {@link #join()}, {@link #join(long)}, {@link
* #join(long, int)}, {@link #sleep(long)}, or {@link #sleep(long, int)},
* methods of this class, then its interrupt status will be cleared and it
* will receive an {@link InterruptedException}.
***
*/
public void interrupt() {
if (this != Thread.currentThread())
checkAccess();
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
nativeInterrupt();
b.interrupt(this);
return;
}
}
nativeInterrupt();
}