wait()和sleep()方法

参考:https://www.cnblogs.com/loren-Yang/p/7538482.html

参考:https://www.cnblogs.com/lyx210019/p/9427146.html#commentform

1、两者的区别

  • 这两个方法来自不同的类分别是Thread和Object  
  • 最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法(锁代码块和方法锁)。  
  • wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用(使用范围)  
  • sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常  
  • sleep方法属于Thread类中方法,表示让一个线程进入睡眠状态,等待一定的时间之后,自动醒来进入到可运行状态,不会马上进入运行状态,因为线程调度机制恢复线程的运行也需要时间,一个线程对象调用了sleep方法之后,并不会释放他所持有的所有对象锁,所以也就不会影响其他进程对象的运行。但在sleep的过程中过程中有可能被其他对象调用它的interrupt(),产生InterruptedException异常,如果你的程序不捕获这个异常,线程就会异常终止,进入TERMINATED状态,如果你的程序捕获了这个异常,那么程序就会继续执行catch语句块(可能还有finally语句块)以及以后的代码。  
  • 注意sleep()方法是一个静态方法,也就是说他只对当前对象有效,通过t.sleep()让t对象进入sleep,这样的做法是错误的,它只会是使当前线程被sleep 而不是t线程  
  •  wait属于Object的成员方法,一旦一个对象调用了wait方法,必须要采用notify()和notifyAll()方法唤醒该进程;如果线程拥有某个或某些对象的同步锁,那么在调用了wait()后,这个线程就会释放它持有的所有同步资源,而不限于这个被调用了wait()方法的对象。wait()方法也同样会在wait的过程中有可能被其他对象调用interrupt()方法而产生  
  • 如果线程A希望立即结束线程B,则可以对线程B对应的Thread实例调用interrupt方法。如果此刻线程B正在wait/sleep/join,则线程B会立刻抛出InterruptedException,在catch() {} 中直接return即可安全地结束线程。
  • 需要注意的是,InterruptedException是线程自己从内部抛出的,并不是interrupt()方法抛出的。对某一线程调用interrupt()时,如果该线程正在执行普通的代码,那么该线程根本就不会抛出InterruptedException。但是,一旦该线程进入到wait()/sleep()/join()后,就会立刻抛出InterruptedException。
<think> 我们讨论的是Java中wait()sleep()方法的区别。根据用户的要求,我们需要: 1. 使用清晰的回答结构 2. 在回答中引用提供的参考内容,并在引用处添加引用标识 3. 生成相关问题 提供的引用内容已经概括了waitsleep的主要区别,我们将在此基础上进行整理扩展。 主要区别点总结(来自引用): 1. **来源不同**:wait()来自Object类,sleep()来自Thread类[^2]。 2. **锁释放行为**:wait()会释放对象锁,而sleep()不会释放锁[^2][^5]。 3. **使用限制**:wait(), notify(), notifyAll()必须在同步代码块(synchronized块)中使用,而sleep()可以在任何地方使用[^2]。 4. **异常捕获**:sleep()必须捕获InterruptedException异常,而wait()不需要(但实际上wait()也会抛出InterruptedException,所以也需要捕获)[^2](注意:这里引用[2]说wait不需要捕获,但实际上需要,因为wait()也会抛出InterruptedException,所以我们需修正这一点)。 5. **唤醒机制**:sleep()时间到自动唤醒,wait()需要其他线程调用notify()或notifyAll()来唤醒[^2][^5]。 6. **线程状态**:sleep()使线程进入TIMED_WAITING(如果指定时间)或WAITING(无限等待?但实际上sleep必须有时间参数,而wait可以无参)状态,wait()使线程进入WAITING或TIMED_WAITING状态[^4]。 但是,引用[4]提到:sleep属于Thread类,让线程进入睡眠状态,等待一定时间后自动醒来,不会释放锁。而引用[5]则强调wait()会释放锁。 我们重新整理并补充一些细节: 1. **锁释放**: - wait():释放锁,这样其他线程可以进入该对象的同步代码块。 - sleep():不释放任何锁,即使当前线程持有锁,其他线程也无法进入同步代码块。 2. **调用位置**: - wait()必须在同步代码块中调用,否则会抛出IllegalMonitorStateException。 - sleep()可以在任何地方调用。 3. **唤醒方式**: - wait():可以通过notify()或notifyAll()唤醒,或者等待超时(如果指定了超时时间)。 - sleep():时间到了自动唤醒,或者被中断(调用interrupt()方法)唤醒。 4. **异常处理**: - 两者都会抛出InterruptedException,因此都需要捕获这个异常。 5. **用途**: - sleep():用于暂停当前线程的执行一段时间,不涉及线程间通信。 - wait():通常用于线程间通信,当某个条件不满足时,线程等待并释放锁,直到条件满足时被其他线程唤醒。 根据以上,我们可以组织回答: ### Java中wait()sleep()方法的区别 #### 1. **方法来源不同** - `wait()` 是 `java.lang.Object` 类中定义的方法[^2]。 - `sleep()` 是 `java.lang.Thread` 类的静态方法[^2]。 #### 2. **锁释放行为** - `wait()`: 调用后会**释放当前对象锁**,允许其他线程获取该锁并执行同步代码块[^2][^5]。 - `sleep()`: 调用后**不会释放任何锁**,即使当前线程持有锁,其他线程也无法进入该对象的同步代码块[^2][^4]。 #### 3. **使用位置限制** - `wait()`: 必须在 `synchronized` 代码块或方法调用,否则会抛出 `IllegalMonitorStateException` 异常[^2]。 - `sleep()`: 可以在任何位置调用,没有同步上下文限制[^2]。 #### 4. **唤醒机制** - `wait()`: 需要其他线程主动调用同一对象的 `notify()` 或 `notifyAll()` 方法唤醒,或等待指定的超时时间后自动唤醒(如果使用带超时的wait)[^5]。 - `sleep()`: 在指定休眠时间结束后自动唤醒,也可通过中断(`interrupt()`)提前唤醒[^4]。 #### 5. **异常处理** - 两者都可能抛出 `InterruptedException` 异常[^4],需要捕获处理: ```java try { Thread.sleep(1000); // sleep示例 } catch (InterruptedException e) { // 处理中断 } synchronized (obj) { try { obj.wait(); // wait示例 } catch (InterruptedException e) { // 处理中断 } } ``` 注意:引用[2]中关于wait不需要捕获异常的说法是不准确的,实际编码中必须处理该异常。 #### 6. **线程状态变化** - `sleep()`: 进入 `TIMED_WAITING` 状态(指定时间)或无限期等待(但实际上sleep必须指定时间,所以是TIMED_WAITING)[^4]。 - `wait()`: 进入 `WAITING` (无超时)或 `TIMED_WAITING` (有超时)状态[^4]。 #### 7. **典型应用场景** - `sleep()`: 用于需要暂停当前线程执行的场景(如定时任务、模拟延迟)[^4]。 - `wait()`: 用于线程间协调,当条件不满足时让出锁资源,等待条件满足后被唤醒(如生产者-消费者模型)[^5]。 > **关键区别总结** > | 特性 | `wait()` | `sleep()` | > |--------------------|---------------------------------------|-------------------------------| > | **锁释放** | 释放锁 | 不释放锁 | > | **调用位置** | 必须在同步块内 | 任意位置 | > | **唤醒方式** | 需主动唤醒或超时 | 超时自动唤醒或中断唤醒 | > | **方法所属类** | `Object` | `Thread` | > | **线程状态** | `WAITING` / `TIMED_WAITING` | `TIMED_WAITING` | ### 相关问题 1. 为什么wait()方法需要在同步代码块中调用? 2. 如何避免使用wait()notify()时出现死锁? 3. 除了wait()sleep(),Java中还有哪些线程控制机制? 4. wait()Condition.await()方法有什么区别? </think> ### Java中`wait()`与`sleep()`方法的区别 #### 1. **方法来源不同** - **`wait()`**:定义在`java.lang.Object`类中[^2][^5],是根类的基础方法。 - **`sleep()`**:定义在`java.lang.Thread`类中[^2][^4],属于线程控制方法。 #### 2. **锁释放行为** | 方法 | 是否会释放锁? | 说明 | |------------|---------------------|------| | **`wait()`** | ✔️ 释放锁 | 调用后立即释放对象锁,其他线程可获取该锁[^2][^5] | | **`sleep()`** | ✖️ 不释放锁 | 线程休眠期间仍持有锁,其他线程无法进入同步块[^2][^4] | #### 3. **使用限制** - **`wait()`**: 必须在`synchronized`代码块内调用,否则抛出`IllegalMonitorStateException`[^2]: ```java synchronized (lock) { lock.wait(); // 正确用法 } ``` - **`sleep()`**: 可在任何位置调用(同步或非同步代码均可)[^2]: ```java Thread.sleep(1000); // 无需同步上下文 ``` #### 4. **唤醒机制** - **`wait()`**: - **依赖外部唤醒**:需其他线程调用`notify()`/`notifyAll()`[^5] - **支持超时**:`wait(long timeout)`在指定时间后自动唤醒 - **`sleep()`**: - **自动唤醒**:休眠结束后自动恢复(如`Thread.sleep(5000)`)[^4] - **可中断唤醒**:通过`interrupt()`强制唤醒[^4] #### 5. **异常处理** | 方法 | 需捕获的异常 | 触发场景 | |-------------|---------------------|------------------| | **`wait()`** | `InterruptedException` | 线程等待时被中断 | | **`sleep()`** | `InterruptedException` | 休眠期间被中断[^4] | #### 6. **线程状态变化** - **`wait()`** → 线程进入`WAITING`或`TIMED_WAITING`状态[^4] - **`sleep()`** → 线程进入`TIMED_WAITING`状态[^4] ![](https://via.placeholder.com/400x200?text=线程状态转换图) *(虚线框:`wait()``sleep()`引起的状态变化)* #### 7. **典型应用场景** - **`wait()`**:线程间协调(如生产者-消费者模型)[^5] ```java // 生产者 synchronized (queue) { while (queue.isFull()) queue.wait(); queue.add(item); queue.notifyAll(); } ``` - **`sleep()`**:延迟执行、定时任务[^4] ```java // 定时检查 while (!taskCompleted) { Thread.sleep(1000); // 每秒检查一次 checkStatus(); } ``` > **关键区别总结** > | 特性 | `wait()` | `sleep()` | > |--------------------|---------------------------------------|-------------------------------| > | **锁释放** | 释放锁 | 不释放锁 | > | **调用位置** | 必须在同步块内 | 任意位置 | > | **唤醒依赖** | 需主动唤醒(`notify()`) | 自动唤醒 | > | **所属类** | `Object` | `Thread` | > | **线程状态** | `WAITING` / `TIMED_WAITING` | `TIMED_WAITING` |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值