当前位置: 首页 > news >正文

java中sleep与wait的区别

在 Java 中,sleep()wait()都用于线程控制,但它们的使用场景、工作机制和功能有本质区别,主要体现在以下几个方面:

1. 所属类不同

  • sleep()java.lang.Thread类的静态方法,通过Thread.sleep()调用。
  • wait()java.lang.Object类的实例方法,必须通过对象实例调用(如obj.wait())。

2. 对锁的影响不同

这是两者最核心的区别:

  • sleep()不会释放锁
    当线程执行sleep()时,会暂停执行指定时间,但持有当前对象的锁不会释放。其他线程无法获取该锁,只能等待sleep()结束后线程继续执行。

  • wait()会释放锁
    当线程执行wait()时,会释放当前对象的锁,并进入该对象的等待队列(waiting pool)。其他线程可以获取该锁并执行同步代码块,直到被notify()/notifyAll()唤醒。

3. 使用场景不同

  • sleep()用于暂停执行
    通常用于控制线程执行的时间间隔,让线程 “休眠” 一段时间后自动恢复,不依赖其他线程的通知。
    示例:

    try {// 线程休眠1秒,不释放锁Thread.sleep(1000); 
    } catch (InterruptedException e) {e.printStackTrace();
    }
    
  • wait()用于线程间通信
    通常用于线程间的协作,让线程等待某个条件满足(如资源就绪),需其他线程调用notify()/notifyAll()唤醒。
    示例:

    synchronized (obj) {try {// 释放obj的锁,进入等待队列obj.wait(); } catch (InterruptedException e) {e.printStackTrace();}
    }
    

4. 唤醒方式不同

  • sleep()自动唤醒
    只需等待指定时间结束,线程会自动从阻塞状态恢复到就绪状态。

  • wait()需主动唤醒
    必须由其他线程调用同一对象notify()(唤醒一个等待线程)或notifyAll()(唤醒所有等待线程)才能恢复。若未被唤醒,线程会一直处于等待状态。
    此外,wait(long timeout)也支持超时自动唤醒(类似sleep()的时间参数)。

5. 调用前提不同

  • sleep()可在任何地方调用
    无需在同步代码块(synchronized)中使用,即使在非同步环境下也能正常工作。

  • wait()必须在同步环境中调用
    必须在synchronized代码块或方法中调用,否则会抛出IllegalMonitorStateException。因为wait()需要释放对象锁,而只有持有锁的线程才能释放锁。

6. 异常处理

两者都会抛出InterruptedException(受检异常),必须捕获或声明抛出。该异常在线程休眠 / 等待时被中断(如其他线程调用interrupt())时触发。

总结对比表

特性sleep()wait()
所属类Thread(静态方法)Object(实例方法)
锁释放不释放锁释放锁
使用场景控制执行间隔线程间通信(等待 / 唤醒)
唤醒方式时间到自动唤醒notify()/notifyAll()或超时
调用前提无需同步环境必须在synchronized中调用

典型使用示例

sleep()示例(不释放锁)
public class SleepDemo {public static void main(String[] args) {Object lock = new Object();new Thread(() -> {synchronized (lock) {System.out.println("线程1获取锁,开始执行");try {// 休眠2秒,不释放lock锁Thread.sleep(2000); } catch (InterruptedException e) {e.printStackTrace();}System.out.println("线程1执行完毕");}}).start();new Thread(() -> {synchronized (lock) {// 需等待线程1释放锁后才能执行System.out.println("线程2获取锁,开始执行");}}).start();}
}

输出:

线程1获取锁,开始执行
(等待2秒)
线程1执行完毕
线程2获取锁,开始执行
wait()示例(释放锁)
public class WaitDemo {public static void main(String[] args) {Object lock = new Object();// 等待线程new Thread(() -> {synchronized (lock) {System.out.println("等待线程:获取锁,开始等待");try {// 释放lock锁,进入等待队列lock.wait(); } catch (InterruptedException e) {e.printStackTrace();}System.out.println("等待线程:被唤醒,继续执行");}}).start();// 唤醒线程new Thread(() -> {try {Thread.sleep(1000); // 确保等待线程先执行} catch (InterruptedException e) {e.printStackTrace();}synchronized (lock) {System.out.println("唤醒线程:获取锁,准备唤醒");lock.notify(); // 唤醒等待线程System.out.println("唤醒线程:执行完毕");}}).start();}
}

输出:

等待线程:获取锁,开始等待
(等待1秒)
唤醒线程:获取锁,准备唤醒
唤醒线程:执行完毕
等待线程:被唤醒,继续执行

总之,sleep()是线程自身的休眠,不涉及锁的释放;wait()是线程间的协作机制,必须配合锁和唤醒操作使用,核心是释放锁并等待通知。

http://www.dtcms.com/a/354778.html

相关文章:

  • ES基础知识
  • PostgreSQL15——常用函数
  • docker一键部署!强大的本地音乐服务器NAS-Music
  • labelme的安装
  • 数据库服务-主从同步-高可用架构MHA
  • vue的动态组件keep-alive实现组件缓存和状态保留
  • 解锁制造业增长密码:MES如何适配行业特性?
  • Linux04:
  • Electron解压缩文件
  • 【实战笔记】OCI Ubuntu 24.04 + TigerVNC + XFCE + Chrome 开机自启全记录
  • [吾爱出品] windows桌面课程表
  • Kafka 4.0 五大 API 选型指南、依赖坐标、上手示例与最佳实践
  • AI智能教育新实践:从作业批改到薄弱项定位,构建个性化学习新路径
  • 深入理解QLabel:Qt中的文本与图像显示控件
  • 云计算学习100天-第30天
  • LaunchScreen是啥?AppDelegate是啥?SceneDelegate是啥?ContentView又是啥?Main.storyboard是啥?
  • 生成式 AI 的 “魔法”:以 GPT 为例,拆解大语言模型(LLM)的训练与推理过程
  • Java线程池深度解析:从原理到实战的完整指南
  • ABAP - CPI - pass header parameter and filter parameter to odata service
  • 【C语言】函数栈帧的创建与销毁
  • 引入资源即针对于不同的屏幕尺寸,调用不同的css文件
  • 开发避坑指南(41):Vue3 提示框proxy.$modal.msgSuccess()提示文本换行解决方案
  • 腾讯混元开源视频拟音模型,破解 AI 视频 “无声” 难题
  • vscode 远程ssh登录免手动输入密码
  • 20.22 QLoRA微调实战:中文语音识别数据准备全流程解密
  • 音合成之二十四 微软VibeVoice语音合成模型
  • 2025通用证书研究:方法论、岗位映射与四证对比
  • 【Bluedroid】A2DP Source设备音频数据读取机制分析(btif_a2dp_source_read_callback)
  • Unity 打包 iOS,Xcode 构建并上传 App Store
  • Java 大视界 -- 基于 Java 的大数据实时流处理在智能电网分布式电源接入与电力系统稳定性维护中的应用(404)