在线程中 sleep 和 wait 有什么区别

本文详细解析了Java中Thread类的sleep方法与Object类的wait方法的区别,包括它们的源码分析、使用场景、锁行为差异及异常处理方式。强调了wait会释放锁而sleep则持有锁的特点。

一、源码如下

  • sleep源码

    public class Thread implements Runnable { 
    public static native void sleep(long millis) throws InterruptedException;
      public static void sleep(long millis, int nanos) throws InterruptedException {
        if (millis < 0) {
          throw new IllegalArgumentException("timeout value is negative");
       }
        if (nanos < 0 || nanos > 999999) {
          throw new IllegalArgumentException(
                    "nanosecond timeout value out of range");
       }
        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
          millis++;
       }
        sleep(millis);
     }
      //...
    }  
    
  • wait源码

    public class Object {
      public final native void wait(long timeout) throws InterruptedException;
      public final void wait(long timeout, int nanos) throws InterruptedException {
        if (timeout < 0) {
          throw new IllegalArgumentException("timeout value is negative");
       }
        if (nanos < 0 || nanos > 999999) {
          throw new IllegalArgumentException(
                    "nanosecond timeout value out of range");
       }
        if (nanos > 0) {
          timeout++;
       }
        wait(timeout);
     }
      //...
    }
    

二、两者区别

1、 sleep 来自 Thread 类,和 wait 来自 Object 类。

2、最大的不同是在等待时 wait 会释放锁,而 sleep 一直持有锁。wait 通常被用于线程间交互,sleep 通常被用于暂停执行。

3、wait,notify和 notifyAll 只能在同步控制方法或者同步控制块里面使用,而 sleep 可以在任何地方使用(使用范围)

4、 sleep 必须捕获异常,而 wait , notify 和 notifyAll 不需要捕获异常

(1) sleep 方法属于 Thread 类中方法,表示让一个线程进入睡眠状态,等待一定的时间之后,自动醒来进入到可运行状态,不会马上进入运行状态,因为线程调度机制恢复线程的运行也需要时间,一个线程对象调用了 sleep方法之后,并不会释放他所持有的所有对象锁,所以也就不会影响其他进程对象的运行。但在 sleep 的过程中过程中有可能被其他对象调用它的 interrupt() ,产生 InterruptedException 异常,如果你的程序不捕获这个异常,线程就会异常终止,进入 TERMINATED 状态,如果你的程序捕获了这个异常,那么程序就会继续执行catch语句块(可能还有 finally 语句块)以及以后的代码。

注意 sleep() 方法是一个静态方法,也就是说他只对当前对象有效,通过 t.sleep() 让t对象进入 sleep ,这样的做法是错误的,它只会是使当前线程被 sleep 而不是 t 线程

(2) wait 属于 Object 的成员方法,一旦一个对象调用了wait方法,必须要采用 notify() 和 notifyAll() 方法唤醒该进程;如果线程拥有某个或某些对象的同步锁,那么在调用了 wait() 后,这个线程就会释放它持有的所有同步资源,而不限于这个被调用了 wait() 方法的对象。 wait() 方法也同样会在 wait 的过程中有可能被其他对象调用 interrupt() 方法而产生 。

### Java 线程 Sleep Wait 方法的区别及用法 #### 所属类的不同 `sleep()` 是 `Thread` 类的静态方法,而 `wait()` 则是 `Object` 类的方法。这意味着 `sleep()` 可以直接通过线程对象调用,而 `wait()` 需要依赖于某个特定的对象实例来调用[^1]。 #### 使用方式上的差异 对于 `sleep(long millis)` 来说,在指定的时间内它会让当前正在执行的线程暂时休眠,并不会释放任何锁资源。相反地,当调用了某对象的 `wait()` 后,不仅会使当前线程进入等待状态直到其他线程唤醒该线程(通过调用相同对象上的 notify 或 notifyAll),而且还会立即放弃对该同步监视器的所有权,即会释放掉已经持有的锁[^2]。 #### 前置条件的要求 为了能够成功调用 `wait()` ,必须先获得相应对象内部锁,通常是在 synchronized 代码块或方法里完成这一操作;但是 `sleep()` 并不需要这样的前置条件就可以正常工作[^3]。 #### 错误处理机制 如果在睡眠期间被打断,则抛出 InterruptedException 异常给上层捕获并做进一步处理。而对于处于 waiting 的线程而言,除了上述提到的通知外,还可以因为超时自动醒来或是同样由于中断事件的发生而导致异常抛出。 ```java // sleep 示例 public class SleepExample { public static void main(String[] args) throws InterruptedException { System.out.println("Start sleeping..."); Thread.sleep(2000); // 让主线程暂停两秒后再继续往下运行 System.out.println("Woke up after two seconds."); } } // wait/notify 示例 class Buffer { private boolean full = false; public synchronized void set(){ while(full){ try{ this.wait(); // 当缓冲区满的时候就让设置数据的线程等待 }catch (InterruptedException e){} } // 设置数据... full=true; this.notify(); } public synchronized int get(){ while(!full){ try{ this.wait(); // 如果没有可取的数据则让消费者线程等待 } catch (InterruptedException e){} } // 获取数据... full=false; this.notify(); return 0; } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Monika、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值