在 java 多线程编程中,wait()
和 sleep()
是两个常用的线程控制方法,但它们在工作原理、使用场景和效果上有显著区别。以下是两者的主要差异:
1. 所属类与基本性质
- sleep():是
thread
类的静态方法,可以直接通过thread.sleep()
调用,用于让当前线程暂停执行指定的时间。 - wait():是
object
类的实例方法,必须通过对象实例调用(如obj.wait()
),主要用于线程间的通信与协调。
2. 锁的行为差异(核心区别)
sleep():
- 不释放锁:当线程调用
sleep()
时,即使线程进入休眠状态,它仍然持有已经获取的任何对象锁。 - 其他线程无法获取被休眠线程持有的锁,导致同步代码块或方法无法被并发执行。
- 不释放锁:当线程调用
wait():
- 释放锁:调用
wait()
会使线程释放当前持有的对象锁,并进入该对象的等待池(waiting pool)。 - 其他线程可以获取该对象的锁并执行同步代码。
- 释放锁:调用
3. 使用场景
sleep():
- 用于让线程暂停执行一段时间,不涉及线程间通信。
- 典型场景:模拟延迟、定时任务、控制执行节奏等。
wait():
- 用于线程间协作,通常与
notify()
/notifyall()
配合使用。 - 典型场景:生产者-消费者模式、线程交替执行等需要条件等待的场景。
- 用于线程间协作,通常与
4. 唤醒机制
sleep():
- 自动唤醒:线程会在指定的时间结束后自动恢复就绪状态。
wait():
- 需要被动唤醒:必须由其他线程调用同一对象的
notify()
或notifyall()
方法才能唤醒。 - 也支持带超时的
wait(long timeout)
,超时后会自动唤醒。
- 需要被动唤醒:必须由其他线程调用同一对象的
5. 调用前提条件
sleep():
- 可以在任何地方调用,不需要在同步代码块中。
wait():
- 必须在同步代码块或同步方法中调用(即必须先获取对象的监视器锁)。
- 否则会抛出
illegalmonitorstateexception
异常。
6. 异常处理
两者都会抛出 interruptedexception
:
- 当线程在休眠或等待期间被其他线程中断时触发。
- 都需要捕获或声明抛出该异常。
7. 线程状态变化
sleep():
- 使线程进入 timed_waiting(带超时)或 waiting(无超时)状态。
wait():
- 使线程进入 waiting(无超时)或 timed_waiting(带超时)状态,并释放锁。
代码示例对比
sleep() 示例(不释放锁)
synchronized (lock) { system.out.println("线程获取锁,开始sleep"); try { thread.sleep(2000); // 休眠2秒,不释放lock锁 } catch (interruptedexception e) { e.printstacktrace(); } system.out.println("线程sleep结束"); } // 其他线程必须等待sleep结束后才能获取锁
wait() 示例(释放锁)
synchronized (lock) { system.out.println("线程获取锁,开始wait"); try { lock.wait(); // 释放lock锁,进入等待队列 } catch (interruptedexception e) { e.printstacktrace(); } system.out.println("线程被唤醒,重新获取锁"); } // 其他线程可以在wait期间获取lock锁
总结对比表
特性 | sleep() | wait() |
---|---|---|
所属类 | thread 类的静态方法 | object 类的实例方法 |
锁释放 | 不释放锁 | 释放锁 |
使用场景 | 线程暂停执行 | 线程间通信与协作 |
唤醒方式 | 自动唤醒(时间到) | 需 notify() /notifyall() 唤醒 |
调用前提 | 无需同步环境 | 必须在 synchronized 中调用 |
异常 | interruptedexception | interruptedexception + illegalmonitorstateexception |
典型用途 | 定时、延迟 | 生产者-消费者、条件等待 |
关键结论
- 锁行为:
sleep()
持有锁不放,wait()
释放锁——这是最本质的区别。 - 协作机制:
wait()
/notify()
是 java 多线程协作的基础机制,而sleep()
只是单纯的线程暂停。 - 使用规范:误用
wait()
(如不在同步块中调用)会导致运行时异常,而sleep()
的使用相对简单。
在实际开发中,应根据是否需要线程间协作来选择使用哪个方法:若只是需要延迟,用 sleep()
;若需要等待某个条件满足(如资源就绪),则用 wait()
。
到此这篇关于java中wait()和sleep()区别小结的文章就介绍到这了,更多相关java wait()和sleep()区别内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论