-
sleep 是 Thread 线程里的一个静态方法,只能作用在当前线程上,即使在 A 线程调用 B 线程的 B.sleep(10) 结果仍是 A 线程休眠10 毫秒,sleep 方法和当前所在的线程有关。而 wait 是 Object 里的实例方法。sleep 可以在任何地方使用,但是 wait 只能在同步方法或同步块中使用;
-
进入 sleep 的线程会在设定时间结束后自动恢复,在唤醒之后不保证能获取到CPU,它会先进入就绪态,与其他线程竞争CPU。但是在休眠期间仍会持有当前锁。而 wait 需要其它线程调用 notify/notifyAll 方法唤醒指定的线程或全部线程才能恢复,并且线程在 wait 期间不会持有当前锁,会释放锁给其它需要调用当前同步方法的线程使用。(注意:notify的作用相当于叫醒睡着的人,而并不会给他分配任务,就是说notify只是让之前调用wait的线程有权利重新参与线程的调度)
-
wait 方法是针对一个被同步代码块加锁的对象,而 sleep 是针对的一个线程。
下面用程序说明两者在代码中实现的区别:
public class MultiThread {
private static class Thread1 implements Runnable{
@Override
public void run() {
//由于 Thread1和下面Thread2内部run方法要用同一对象作为监视器,如果用this则Thread1和Threa2的this不是同一对象
//所以用MultiThread.class这个字节码对象,当前虚拟机里引用这个变量时指向的都是同一个对象
synchronized(MultiThread.class){
System.out.println("enter thread1 ...");
System.out.println("thread1 is waiting");
try{
//释放锁有两种方式:(1)程序自然离开监视器的范围,即离开synchronized关键字管辖的代码范围
//(2)在synchronized关键字管辖的代码内部调用监视器对象的wait()方法。这里使用wait方法
MultiThread.class.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("thread1 is going on ...");
System.out.println("thread1 is being over!");
}
}
}
private static class Thread2 implements Runnable{
@Override
public void run() {
//notify方法并不释放锁,即使thread2调用了下面的sleep方法休息10ms,但thread1仍然不会执行
//因为thread2没有释放锁,所以Thread1得不到锁而无法执行
synchronized(MultiThread.class){
System.out.println("enter thread2 ...");
System.out.println("thread2 notify other thread can release wait status ...");
//这里唤醒 Thread1 里 wait 的MultiThread.class对象
MultiThread.class.notify();
System.out.println("thread2 is sleeping ten millisecond ...");
try{
Thread.sleep(10);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("thread2 is going on ...");
System.out.println("thread2 is being over!");
}
}
}
public static void main(String[] args) {
new Thread(new Thread1()).start();
try{
Thread.sleep(10);
}catch(InterruptedException e){
e.printStackTrace();
}
new Thread(new Thread2()).start();
}
}
运行结果是:

可以看出在调用 new Thread(new Thread2()).start() 方法后 thread2 开始运行并持有当前加锁的对象 MultiThread.class,因为在 thread1 里执行了MultiThread.class.wait() 方法释放了此锁的对象,所以会输出 thread2 里的打印方法,然后即使线程 thread2 休眠了 10 毫秒,也还是先打印了 thread2 里休眠代码后边的两行输出,说明在 thread2 休眠时还是持有当前锁的对象,当 Thread2 线程执行完毕,这时 thread1 才会再次获得当前锁的对象,并继续执行剩下的方法。
网友评论