1、二者的来源
sleep(),是Thread下面的静态方法/静态本地方法。
wait(),是Object()的final方法。
2、源码分析
a、sleep()
1 public static void sleep(long millis, int nanos) 2 throws InterruptedException { 3 if (millis < 0) { 4 throw new IllegalArgumentException("timeout value is negative"); 5 } 6 7 if (nanos < 0 || nanos > 999999) { 8 throw new IllegalArgumentException( 9 "nanosecond timeout value out of range"); 10 } 12 if (nanos >= 500000 || (nanos != 0 && millis == 0)) { 13 millis++; 14 } 15 16 sleep(millis); 17 }
当调用sleep(millis,nanos)的时候,内部调用的sleep(mills),如下:
public static native void sleep(long millis) throws InterruptedException;
这是一个静态的本地方法
由一句话比较重要::: The thread does not lose ownership of any monitors.调用该方法的线程不会失去任何的监控。 不会失去该线程原来拥有的所有锁。
实例:
一个实体类User
1 public class User { 2 private int age; 3 4 public int getAge() { 5 return age; 6 } 7 8 @Override 9 public String toString() { 10 return "User [age=" + age + "]"; 11 } 12 13 public void setAge(int age) { 14 this.age = age; 15 } 16 17 }
对该实体类的操作
1 public class Main { 2 3 public static void main(String[] args) { 4 5 final User user = new User(); 6 user.setAge(10); 7 8 synchronized (user) { 9 try { 10 System.out.println("当前线程 <---->" 11 + Thread.currentThread().getName() + "<-----> 准备休眠"); 12 13 Thread.sleep(10000);// 当前线程休眠 14 15 System.out.println("当前线程 <---->" 16 + Thread.currentThread().getName() + "<-----> 完成休眠"); 17 18 // 创建新的线程,对当前持锁对象执行相关操作 19 new Thread("new thread") { 20 public void run() { 21 System.out.println("当前线程 --->" 22 + Thread.currentThread().getName()); 23 System.out.println(user.getAge()); 24 }; 25 }.start(); 26 27 } catch (InterruptedException e) { 28 // TODO Auto-generated catch block 29 e.printStackTrace(); 30 } 31 } 32 } 33 }
执行结果:
当前线程 <---->main<-----> 准备休眠 当前线程 <---->main<-----> 完成休眠 当前线程 ---> new thread 10
所以当在一个synchronized方法中调用sleep()时,线程虽然休眠了,但是对象的机锁没有被释放,其他线程仍然无法访问这个对象。而wait()方法则会在线程休眠的同时释放掉机锁,其他线程可以访问该对象。所以只有在synchronized 块结束的时候,线程才会释放相应的锁。
b、wait()
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
调用该方法的线程必须要拥有对象的控制权。调用之后,就会释放控制权,直到被其他的线程唤醒(notify() | notifyAll()) 。
The thread then waits until it can re-obtain ownership of the monitor and resumes execution.
之后,被唤醒的线程就继续等待,直到 重新获取对象的控制权。
1 public final void wait() throws InterruptedException { 2 wait(0); 3 }
调用wait(0)方法--final native
public final native void wait(long timeout) throws InterruptedException;
The specified amount of real time has elapsed, more or less. If timeout is zero, however, then real time is not taken into consideration and the thread simply waits until notified.Then removed from the wait set for this object and re-enabled for thread scheduling. 到达wait时间或者被唤醒(还有一种被唤醒的方式--spurious wakeup,详细可以查看相关API),就会从线程的wait set中移除,等待重新被调度。
欢迎拍砖