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

java多线程sleep() 和 wait() 有什么区别?

大家好,我是锋哥。今天分享关于【java多线程sleep() 和 wait() 有什么区别?】面试题。希望对大家有帮助;

java多线程sleep() 和 wait() 有什么区别?

在Java中,sleep()wait() 都是多线程编程中常用的控制线程执行的方法。它们看似有相似之处,但实际上在应用场景和行为机制上有很多不同之处。本文将详细阐述这两者的区别,并帮助大家更好地理解如何在多线程编程中正确使用它们。

1. sleep() 方法

sleep()Thread 类中的一个静态方法,用于让当前线程暂停执行一段时间。调用 sleep() 方法的线程会进入“休眠”状态,暂停执行直到指定的时间过去。sleep() 方法不会释放锁,它只是让线程在指定的时间内停止运行。

语法:
Thread.sleep(long millis) throws InterruptedException
Thread.sleep(long millis, int nanos) throws InterruptedException
  • millis:睡眠的毫秒数
  • nanos:额外的纳秒数(适用于更精确的时间控制)
特点:
  1. 不释放锁:调用 sleep() 后,当前线程依然持有它在执行之前获得的锁,直到 sleep() 方法结束。这意味着如果当前线程持有一个对象的锁,其他线程不能访问该对象的同步方法或同步块。
  2. 不会释放对象的监视器:由于 sleep() 不涉及等待或释放对象监视器,它不会改变线程的同步状态。
  3. 阻塞当前线程sleep() 方法只是简单地让线程进入一个休眠状态,过了指定时间后,线程会自动恢复执行。
示例:
public class SleepExample {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("Thread going to sleep...");
        Thread.sleep(2000); // 让当前线程休眠2秒
        System.out.println("Thread woke up after 2 seconds.");
    }
}

2. wait() 方法

wait()Object 类中的一个实例方法,它是用于线程之间通信的工具。wait() 方法会导致当前线程放弃对象的监视器,并使当前线程进入“等待”状态,直到其他线程通过调用同一对象的 notify()notifyAll() 方法来唤醒它。

语法:
public final void wait() throws InterruptedException
public final void wait(long timeout) throws InterruptedException
public final void wait(long timeout, int nanos) throws InterruptedException
  • timeout:最大等待时间,单位是毫秒
  • nanos:额外的纳秒时间,用于更精确的等待控制
特点:
  1. 释放锁:当线程调用 wait() 方法时,它会释放当前对象的锁,并进入该对象的等待池中,直到其他线程调用该对象的 notify() 或 notifyAll() 方法来唤醒它。wait() 方法通常与 synchronized 关键字一起使用,以保证在多个线程之间的安全通信。
  2. 线程通信机制wait() 用于线程之间的协调和通信。它使线程等待某个条件的发生,然后才能继续执行。
  3. 阻塞线程:调用 wait() 后,线程会进入阻塞状态,并且在被其他线程通过 notify() 或 notifyAll() 唤醒之前无法继续执行。
示例:
class Counter {
    private int count = 0;
    
    public synchronized void increment() throws InterruptedException {
        while (count == 5) {
            wait();  // 当count为5时,等待其他线程通知
        }
        count++;
        System.out.println("Count incremented to: " + count);
        notify();  // 通知其他等待的线程
    }
    
    public synchronized void decrement() throws InterruptedException {
        while (count == 0) {
            wait();  // 当count为0时,等待其他线程通知
        }
        count--;
        System.out.println("Count decremented to: " + count);
        notify();  // 通知其他等待的线程
    }
}

public class WaitExample {
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();
        
        // Increment thread
        Thread incrementThread = new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    counter.increment();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        
        // Decrement thread
        Thread decrementThread = new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    counter.decrement();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        
        incrementThread.start();
        decrementThread.start();
        
        incrementThread.join();
        decrementThread.join();
    }
}

3. sleep() 和 wait() 的主要区别

特性sleep()wait()
所属类Thread 类中的静态方法Object 类中的实例方法
释放锁不释放锁会释放锁
阻塞线程的方式阻塞当前线程指定的时间阻塞当前线程直到被其他线程通过 notify() 或 notifyAll() 唤醒
适用场景用于让线程暂停执行,不关心线程间的交互用于线程间的协作,适合线程之间的等待与通知机制
异常处理会抛出 InterruptedException 异常会抛出 InterruptedException 异常
常与 synchronized不需要与 synchronized 一起使用通常与 synchronized 一起使用,以保证线程安全

4. 使用场景总结

  • sleep():通常用于让当前线程暂停执行一段时间,不涉及线程间的协调或通信。适用于定时任务、暂停、等待特定时间后继续执行等场景。

  • wait():通常用于线程间的协调与通信,适用于生产者-消费者模型、线程池中的任务等待等需要同步和通信的场景。调用 wait() 时必须在 synchronized 块中使用,以确保线程安全。

5. 小结

尽管 sleep()wait() 都会导致线程进入阻塞状态,但它们的应用场景和工作机制有所不同。sleep() 用于简单地让线程暂停一段时间,而 wait() 则用于线程间的协作,通常在多线程共享资源时配合 synchronized 使用。在实际开发中,我们需要根据具体的需求来选择合适的机制,以保证程序的正确性和高效性。


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

相关文章:

  • 深入了解Git、GitHub、GitLab及其应用技巧
  • 如何线程安全的使用HashMap
  • Unity 网格模型及优化
  • 【网络】应用层——HTTP协议
  • 多媒体信息检索
  • IntelliJ IDEA的快捷键
  • Shiro权限刷新
  • 「C/C++」C/C++标准库 之 #include<cstdlib> 通用工具函数库
  • hive表批量造数据
  • 08、Java学习-面向对象中级:
  • MySQL约束管理
  • 微服务day04
  • 技术速递|.NET 9 中 System.Text.Json 的新增功能
  • Linux命令 - linux索引节点、硬链接、软链接的介绍与使用
  • 一个简单ASP.NET购物车设计
  • 从0开始linux(24)——文件(5)磁盘文件系统
  • SpringBoot3中swagger无法使用
  • C#-密封类、密封方法
  • acmessl.cn提供接口API方式申请免费ssl证书
  • 第 2 章 - Go语言环境搭建
  • C++builder中的人工智能(16):神经网络中的SoftPlus激活函数
  • 网络安全应急响应(归纳)
  • AscendC从入门到精通系列(一)初步感知AscendC
  • 「Mac玩转仓颉内测版3」入门篇3 - Cangjie的基本语法与结构
  • rediss数据结构及其底层实现
  • C++代码优化(三): 决不要重新定义继承而来的缺省参数值