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

Java 中 wait 和 sleep 的区别:从原理到实践全解析

前言

在 Java 多线程编程中,waitsleep 是两位重量级角色。尽管它们都可以让线程暂停执行,但在实际使用中却有着天壤之别。很多人初学时对这两者感到困惑,甚至在面试中被考官“灵魂拷问”:waitsleep 有什么区别?”。今天,我们就从它们的原理、使用场景、常见误区等方面做一个详细的讲解。


一、基本概念

1. sleep 方法

Thread.sleep(long millis) 是 Java 提供的线程暂停工具,用于让当前线程休眠指定时间。

  • 属于 Thread 的静态方法。
  • 不需要依赖同步锁。
  • 休眠时间结束后,线程会自动从阻塞状态变为可运行状态。

示例:

System.out.println("开始休眠");
Thread.sleep(2000); // 当前线程休眠 2 秒
System.out.println("休眠结束");
2. wait 方法

wait() 是 Object 类的实例方法,用于让当前线程进入等待状态,直到被唤醒。

  • 属于 Object 的实例方法。
  • 必须在 同步代码块或同步方法 中调用,否则会抛出 IllegalMonitorStateException
  • 等待的线程需要通过 notify()notifyAll() 唤醒。

示例:

synchronized (lock) {
    System.out.println("线程进入等待状态");
    lock.wait(); // 线程释放锁,进入等待状态
    System.out.println("线程被唤醒");
}

二、核心区别

1. 所属类不同
方法所属类作用对象
sleepThread当前线程
waitObject持有对象锁的线程
2. 是否释放锁
方法是否释放锁
sleep不释放锁
wait释放锁

解释

  • sleep 不会影响同步代码块中其他线程的执行,因为它只是让线程休眠,锁仍然被持有。
  • wait 会主动释放锁,让其他线程有机会获取锁并执行。
3. 触发方式不同
方法触发恢复方式
sleep休眠时间结束后自动恢复
wait必须被 notifynotifyAll 唤醒
4. 使用场景不同
方法使用场景
sleep暂停线程,模拟延迟
wait线程间通信,等待某个条件满足时恢复

三、实践解析

1. sleep 的使用场景:模拟延迟

在某些场景中,我们需要让线程暂停一段时间,例如定时任务或动画效果的实现。

示例:

public class SleepDemo {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("倒计时开始:");
        for (int i = 5; i > 0; i--) {
            System.out.println(i);
            Thread.sleep(1000); // 每隔 1 秒打印一次
        }
        System.out.println("倒计时结束!");
    }
}

运行结果:

倒计时开始:
5
4
3
2
1
倒计时结束!

2. wait 的使用场景:线程间通信

在多线程编程中,waitnotify 是线程间通信的核心工具。例如,生产者-消费者模式中,生产者需要等待消费者处理完消息后继续生产。

示例:

public class WaitNotifyDemo {
    private static final Object lock = new Object();
    private static boolean condition = false;

    public static void main(String[] args) {
        Thread producer = new Thread(() -> {
            synchronized (lock) {
                System.out.println("生产者:准备生产数据");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                condition = true;
                System.out.println("生产者:数据已就绪,唤醒消费者");
                lock.notify();
            }
        });

        Thread consumer = new Thread(() -> {
            synchronized (lock) {
                while (!condition) {
                    try {
                        System.out.println("消费者:数据未就绪,进入等待");
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("消费者:数据已处理");
            }
        });

        consumer.start();
        producer.start();
    }
}

运行结果:

消费者:数据未就绪,进入等待
生产者:准备生产数据
生产者:数据已就绪,唤醒消费者
消费者:数据已处理

四、常见误区

1. 在非同步块中调用 wait

wait 方法必须在同步代码块或同步方法中调用,否则会抛出异常。

错误示例:

Object lock = new Object();
lock.wait(); // 会抛出 IllegalMonitorStateException

正确示例:

synchronized (lock) {
    lock.wait(); // 正常工作
}
2. 忘记调用 notifynotifyAll

使用 wait 后,必须确保在某个条件满足时调用 notifynotifyAll 唤醒线程,否则等待的线程将一直处于阻塞状态。


五、总结

特性sleepwait
所属类ThreadObject
是否释放锁
唤醒方式自动notifynotifyAll
使用场景模拟延迟、定时任务线程间通信、等待条件
记忆小贴士:
  • 如果只是简单地让线程暂停一段时间,使用 sleep
  • 如果需要线程之间协作,等待某个条件时,使用 wait 搭配 notify

掌握了 waitsleep 的区别后,相信你在面对多线程开发时会更加得心应手!如果你还有其他疑问,欢迎留言讨论~ 😊


http://www.kler.cn/a/446419.html

相关文章:

  • STM32 高级 物联网通信之CAN通讯
  • 【网络云计算】2024第51周-每日【2024/12/17】小测-理论-解析
  • 服务器防火墙设置某个端口号只允许固定 ip地址访问
  • 【python虚拟环境安装】linux centos 下的python虚拟环境配置
  • [react]redux异步处理和重写useDispatch
  • 【人工智能】从TF-IDF到BERT:Python实现文本分类的全面指南
  • lua dofile 传参数
  • GhostRace: Exploiting and Mitigating Speculative Race Conditions-记录
  • 基于 Python 将 PDF 转 Markdown 并拆解为 JSON,支持自定义标题处理
  • Odoo:免费开源ERP的AI技术赋能出海企业电子商务应用介绍
  • Python Turtle图形库基本命令详解
  • leetcode之hot100---160相交链表(C++)
  • MFC/C++学习系列之简单记录2——thread和Release
  • 【服务器】MyBatis是如何在java中使用并进行分页的?
  • 中阳科技的量化交易模型:从理论到实践的全面探索
  • 1688跨境代购代采:API赋能的自动化与信息化革新
  • 【NLP 18、新词发现和TF·IDF】
  • git中的tag标签远程管理
  • Linux禁用网络、开启网络
  • Docker:Dockerfile(补充四)
  • 贪心算法 greedy
  • CEF127 编译指南 MacOS 篇 - 拉取 CEF 源码(五)
  • 多进程、多线程、分布式测试支持-pytest-xdis插件
  • 零基础学习OpenFOAM:从流体力学与人工智能的交叉科学,流场预测与重构,气动信息预测,基于深度强化学习的气动优化出发
  • 计算机网络:运输层 —— TCP 的选择确认(SACK)
  • WPF 用Vlc.DotNet.Wpf实现视频播放、停止、暂停功能