关于java中wait()和sleep()方法间的区别

本文通过一个具体的Java代码示例,详细解释了wait()和sleep()方法的不同之处。重点在于wait()会释放对象锁并等待通知,而sleep()仅使线程暂停但不释放锁。
//摘取自一位前辈的测试代码
public class TestD {

    public static void main(String[] args) {
    	//同时开始两个线程,先进行第一个线程Thread1,再进行第二个线程Thread2
        new Thread(new Thread1()).start();
        try {
            Thread.sleep(5000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        new Thread(new Thread2()).start();
    }
    
    
    private static class Thread1 implements Runnable{
        public void run(){
            synchronized (TestD.class) {
            System.out.println("enter thread1...");    
            System.out.println("thread1 is waiting...");
            try {
                //调用wait()方法,线程会放弃对象锁,进入等待此对象的等待锁定池
                TestD.class.wait();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("thread1 is going on ....");
            System.out.println("thread1 is over!!!");
            }
        }
    }
    
    private static class Thread2 implements Runnable{
        @Override
        public void run(){
            synchronized (TestD.class) {
                System.out.println("enter thread2....");
                System.out.println("thread2 is sleep....");
                //只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
                TestD.class.notify();
                //==================
                //区别
                //如果我们把代码:TestD.class.notify();给注释掉,即TestD.class调用了wait()方法,但是没有调用notify()
                //方法,则线程永远处于挂起状态。
                try {
                    //sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,
                    //但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
                    //在调用sleep()方法的过程中,线程不会释放对象锁。
                    Thread.sleep(5000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println("thread2 is going on....");
                System.out.println("thread2 is over!!!");
            }
        }
    }
}

因为这里的代码是直接引用一位前辈的代码,讲解是自己加的,尊重原创,这里就发成转载的吧

初步看java中的wait()和sleep()方法,感觉这两个方法的区别并不大。

1.sleep是让线程让出CPU来让其他线程使用,然而并不释放对象锁,与之相对的,wait同样进行让线程让出CPU的操作,然而,wait会要求线程释放对象锁,同时在调用notify方法之前,放弃重新获得对象锁的可能性。

<think> 我们讨论的是Javawait()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():通常用于线程通信,当某个条件不满足时,线程等待并释放锁,直到条件满足时被其他线程唤醒。 根据以上,我们可以组织回答: ### Javawait()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` |
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值