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;
从官方的注释可以知道,当前线程对要持有当前对象的资源锁,并且当前线程会释放锁。
而且要调用notify唤醒wait的线程时,必须先持有对象的资源锁,从这里可以知道,不管是调用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;
发现官方注释上面,sleep的时候是没有 释放资源锁的。这就是跟wait最大的区别.
下面写对应例子验证:
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
从上面的输出可以看出,当调用wait的时候,其他线程是可以继续调用funForwait方法并且访问
Log.e("@@@", "wait begin " + id);
而调用sleep的则不行,从这里可以看出,wait的时候,线程是释放了对Object的锁,而sleep却没有,所以
Log.e("@@@", "sleep begin : " + id);
这段代码当第一个线程进入sleep的时候,其他线程被挂起并且访问不了这段代码,原因是因为当前线程还是持有Object资源锁。
如果想要中断当前正在挂起等待的线程,可以调用
/**
* <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();
}
网友评论