sleep 和 wait 的区别?

发布时间 2023-07-13 15:46:40作者: 一只礼貌狗

一. 介绍

  sleep() : 是Thread类方法,用于使当前线程暂停执行一段时间。它可以被使用在多线程编程中,用于控制线程的执行速度或者创建时间延迟。

      参数:     long millis   : 参数表示线程休眠的毫秒数。 例如,如果调用Thread.sleep(1000),则当前线程会休眠 1000 毫秒(即 1 秒);

           int nanos    : 参数nanos表示要暂停的时间长度的额外部分,以纳秒为单位 ; 

  wait() :   是Object类的方法,让当前线程进入等待(阻塞)WAITTING 状态,将线程放入到等待队列中,并释放对象锁。

      参数   long timeout: 参数timeout(毫秒)时间后会被自动唤醒 ;

           int nanos    : 参数nanos表示额外时间(以毫微秒为单位,范围是 0-999999);wait(500, 50000),先执行5000毫微秒,执行结束后调用timeout执行。 

 

二. 代码展示

   public static void main(String[] args) {
        Object o = new Object();
        long start = System.currentTimeMillis();

        // 开启一个线程,线程内部使用wait() 方法 释放线程并让线程进入等待。
        new Thread(() -> {
            System.out.println("我是wait()线程");
            synchronized (o) {
                System.out.println("线程wait()等待将执行");
                try {
                    System.out.println("线程wait() 已释放");
                    o.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                long end = System.currentTimeMillis();
                System.out.println("线程wait()已唤醒,执行完毕,执行时间:" + (end - start));
            }
        }).start();

        //  开启一个线程,用于执行sleep()方法,使其线程暂时休眠。
        new Thread(() -> {
            System.out.println("我是Thread.sleep线程");
            synchronized (o) {
                System.out.println("线程Thread.sleep执行中");
                try {
                    Thread.sleep(5000);
                    o.notify();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                long end = System.currentTimeMillis();
                System.out.println("线程Thread.sleep执行结束,用时" + (end - start));
            }
        }).start();

    }

  执行过程:

    - new 两个Thread线程类 ,通过start() 方法执行,开启抢占式;

    - 使用 synchronized 关键字,锁定执行线程。

    - 假设wait() 抢到线程调度,将会执行o.wait(); 释放该线程锁,进入等待状态,此时该线程不会自动唤醒,需要等待o.notify()或o.notifyAll() 方法,wait()线程才会重新进入就绪状态,准备获得对象锁进入运行状态 

    - Thread.sleep线程,会在o.wait() 方法执行后,获取到线权,执行Thread.sleep() 方法,该方法不会释放线程,会导致线程暂停执行,监控状态依然保持,在达到指定执行时间后会自动恢复。

    - Thread.sleep线程恢复后,将执行o.notify() 方法(当前线程不会马上释放该对象锁,要等到同步块或者同步方法执行完后,当前线程才会释放锁),唤醒 wait() 线程,顺序执行代码后结束;

    - wait()线程进入运行状态,顺序执行代码后结束。

 

三. 区别

  sleep:是指让当前线程暂停执行一段时间(即睡眠),然后再继续执行。在睡眠期间,线程会进入阻塞状态,不会占用CPU资源。sleep 的作用是为了暂停程序的执行,通常用于实现时间延迟的需求或控制程序的执行频率。

  wait:是指在多线程编程中,调用对象的某个方法,使当前线程等待,直到其他线程通知或满足特定条件时再继续执行。在调用 wait 方法后,当前线程会释放锁并进入等待状态,直到其他线程通过调用对象的 notify 或 notifyAll 方法来唤醒等待的线程。

  总结: sleep 是线程级别的操作,可以让当前线程暂停一段时间。

      wait 是对象级别的操作,使当前线程等待其他线程的通知或特定条件的满足。

   

四. 拓展

  1. 线程的状态:   

    创建状态: 当用new操作符创建一个线程的时候

     就绪状态: 调用start方法,处于就绪状态的线程并不一定马上就执行run方法,还需要等待CPU的调度。

    运行状态: CPU开始调度线程,并开始执行Run方法。

    阻塞状态: 线程的执行过程中可能因为一些原因进入阻塞状态,比如调用sleep方法,获取尝试得到一个等待。

    等待状态(Waiting): 使用notify、notifyAll、join方法唤醒。

    死亡状态: Run方法执行完成或者执行终于遇到异常。

 

  2. Thread.sleep(1000)  和 o.wait(1000) 的区别;

   两者参数均为1s,也就是多,两者执行都会等待1s,但有本质上的区别

   Thread.sleep() 在暂停期间,线程不会释放持有的任何锁或资源。一旦暂停时间结束,线程将被唤醒并可以重新参与竞争执行。

   wait()方法,必须在一个同步代码块或同步方法中,并且线程必须获取到对象的监视器锁。wait()方法调用后,线程进入等待状态并释放持有的监视器锁。其他线程可以进入该对象的同步代码块或同步方法,并对其进行操作。当满足某个条件时,或者超过最长等待时间后,线程将被唤醒并尝试重新获取监视器锁以继续执行