详解Java中的sleep()和wait()的区别
在Java编程语言中,`sleep()` 和 `wait()` 都是用来控制线程执行的重要方法,但它们的作用和使用场景有着显著的区别。以下是这两个方法的详细解释: 1. **`Thread.sleep(long milliseconds)`** - `sleep()` 方法是 `java.lang.Thread` 类的一个静态方法,它用于使当前正在执行的线程暂时停止执行,指定的毫秒数后自动恢复。这个方法主要用于短时间的线程休眠,以避免线程过度占用CPU资源或实现简单的定时效果。 - 当调用 `sleep()` 时,线程会保持对已获得的所有锁的持有权,不会释放任何锁。这意味着其他线程不能因为这个线程进入睡眠状态而立即获得这些锁。 - `sleep()` 方法不会抛出 `InterruptedException`,除非被中断,否则线程会在指定时间后自动醒来,继续执行后续代码。 - 使用示例: ```java try { Thread.sleep(5000); // 线程将休眠5秒 } catch (InterruptedException e) { e.printStackTrace(); } ``` 2. **`Object.wait()`** - `wait()` 方法是 `java.lang.Object` 类的一个实例方法,它只能在同步块或同步方法中使用,因为它涉及到对象锁的管理。当一个线程调用对象的 `wait()` 方法时,它会释放当前对象的锁,然后进入该对象的等待池,等待其他线程唤醒。 - 调用 `wait()` 的线程需要先获得对象的锁,否则会抛出 `IllegalMonitorStateException`。 - `wait()` 可以有参数,表示等待的毫秒数,也可以无参数,表示无限等待。如果设置了时间,当等待时间结束后,线程会自动从等待池返回到锁池,尝试重新获得对象锁;如果没有设置时间,线程会一直等待直到被唤醒。 - 线程被唤醒通常有两种方式:一是通过其他线程调用该对象的 `notify()` 或 `notifyAll()` 方法,二是因为中断(`Thread.interrupt()`)。 - 使用示例: ```java synchronized (object) { object.wait(); // 线程会释放对象锁并进入等待状态 } ``` 3. **`Object.notify()` 和 `Object.notifyAll()`** - 这两个方法也是 `java.lang.Object` 类的实例方法,用于唤醒等待在该对象上的线程。`notify()` 只随机唤醒一个等待线程,而 `notifyAll()` 唤醒所有等待线程。 - 唤醒的线程不会立即执行,而是会尝试重新获得对象锁,成功后才会从等待池进入锁池并继续执行。 总结一下,`sleep()` 主要是用来让线程短暂休眠,不涉及任何锁的问题,而 `wait()` 是线程间协作的关键,用于线程间的同步和通信,涉及到对象锁的释放和重新获取。理解并正确使用这两个方法是编写多线程程序的关键,可以有效地控制线程的执行顺序和资源的分配,避免出现死锁等问题。在设计并发程序时,应根据具体需求选择合适的方法。