Java 中 sleep 和 wait 的区别

  1. sleep 是 Thread 线程里的一个静态方法,只能作用在当前线程上,即使在 A 线程调用 B 线程的 B.sleep(10) 结果仍是 A 线程休眠10 毫秒,sleep 方法和当前所在的线程有关。而 wait 是 Object 里的实例方法。sleep 可以在任何地方使用,但是 wait 只能在同步方法或同步块中使用;

  2. 进入 sleep 的线程会在设定时间结束后自动恢复,在唤醒之后不保证能获取到CPU,它会先进入就绪态,与其他线程竞争CPU。但是在休眠期间仍会持有当前锁。而 wait 需要其它线程调用 notify/notifyAll 方法唤醒指定的线程或全部线程才能恢复,并且线程在 wait 期间不会持有当前锁,会释放锁给其它需要调用当前同步方法的线程使用。(注意:notify的作用相当于叫醒睡着的人,而并不会给他分配任务,就是说notify只是让之前调用wait的线程有权利重新参与线程的调度)

  3. 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 才会再次获得当前锁的对象,并继续执行剩下的方法。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • sleep()方法 sleep()使当前线程进入停滞状态(阻塞当前线程),让出CUP的使用、目的是不让当前线程独自...
    Leon_hy阅读 828评论 0 1
  • 1、这两个方法来自不同的类分别是,sleep来自Thread类,和wait来自Object类。 sleep是Thr...
    willcoder阅读 24,201评论 2 12
  • Java多线程学习 [-] 一扩展javalangThread类 二实现javalangRunnable接口 三T...
    影驰阅读 2,987评论 1 18
  • 本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。 首先讲...
    李欣阳阅读 2,503评论 1 15
  • sleep()和wait()的区别 Java中的多线程是一种抢占式的机制而不是分时机制。线程主要有以下几种状态:可...
    我的天呐0_0阅读 2,032评论 1 1