【Java】线程暂停比拼:wait() 和 sleep()的较量

server/2024/9/23 4:13:21/

欢迎浏览高耳机的博客

希望我们彼此都有更好的收获

感谢三连支持!

在Java多线程编程中,合理地控制线程的执行是至关重要的。wait()sleep()是两个常用的方法,它们都可以用来暂停线程的执行,但它们之间存在着显著的差异。本文将详细探讨这两个方法的区别,并提供一个实际的编程示例来展示如何使用它们来控制线程的执行顺序。

               当你被罚站时,需要等待解除罚站的指令才能离开;

               而当你睡觉时,到了一定时间自然就会醒来;

wait()sleep()概述

wait()

    定义wait()Object类的一个方法,它使得调用它的线程释放对象的锁,并进入对象的等待池(wait set)。

    用途:主要用于线程间的协作,特别是当一个线程需要等待另一个线程完成某些操作时。

    锁状态:调用wait()的线程必须拥有对象的锁,并且在调用后会释放这个锁。

sleep()

    定义sleep()Thread类的一个静态方法,它使得调用它的线程暂停执行指定的时间。

    用途:通常用于控制线程的执行时间,或者在不释放锁的情况下让其他线程有机会执行。

    锁状态:调用sleep()的线程不会释放任何锁。

wait()必须在同步方法或块中调用。

sleep()可以在任何地方调用。

区别详解

锁状态和对象监视器

    wait()需要在同步方法或块中调用,因为它依赖于对象的锁。调用后,线程会释放锁并进入等待状态。

    sleep()可以在任何地方调用,不需要在同步方法或块中,且不会释放任何锁。

响应中断

           在wait()sleep()期间,如果线程被中断,都会抛出InterruptedException异常。

用途

    wait()通常用于线程间的协作,如生产者-消费者问题。

    sleep()通常用于控制线程的执行时间,或者在不释放锁的情况下让其他线程有机会执行。

返回到执行状态

    wait()在被唤醒后,需要重新获得对象的锁才能继续执行。

    sleep()在睡眠时间结束后自动继续执行,不需要重新获得锁。

实际编程示例

以下是一个使用wait()sleep()来控制线程执行顺序的示例:

    有三个线程,线程名称分别为:a,b,c。 每个线程打印自己的名称。需要让他们同时启动,并按 c,b,a的顺序打印

使用 wait() 实现: 

java">package Thread;public class Demo11 {private static Object locker = new Object();private static int state = 1;public static void main(String[] args) throws InterruptedException {//通过state这个变量作为判断条件,不满足该条件的线程进入等待,满足条件的线程则先打印,//然后改变条件,通过notify唤醒其他线程,继续判断,打印;Thread thread1 = new Thread(() -> {synchronized (locker) {while(state != 1) {try {locker.wait();}catch (InterruptedException e) {e.printStackTrace();}}System.out.println("C");state = 2;locker.notify();}});Thread thread2 = new Thread(() -> {synchronized (locker) {while(state != 2) {try {locker.wait();}catch (InterruptedException e) {e.printStackTrace();}}System.out.println("B");state = 3;locker.notify();}});Thread thread3 = new Thread(() -> {synchronized (locker) {while(state != 3) {try {locker.wait();}catch (InterruptedException e) {e.printStackTrace();}}System.out.println("A");state = 1;locker.notify();}});thread1.start();thread2.start();thread3.start();thread1.join();thread2.join();thread3.join();}
}

在这个示例中,我们使用了一个共享对象locker作为锁,并通过state变量来控制线程的执行顺序。每个线程在执行前都会检查state变量,如果不符合条件,就会调用wait()方法等待。当一个线程执行完毕后,它会更新state变量并调用notify()方法来唤醒其他等待的线程。

使用 sleep() 实现

java">package Thread;public class Demo13 {//sleep版
//    有三个线程,线程名称分别为:a,b,c。
//    每个线程打印自己的名称。
//    需要让他们同时启动,并按 c,b,a的顺序打印public static void main(String[] args) throws InterruptedException {Thread thread1 = new Thread(() -> {try {Thread.sleep(200);}catch (InterruptedException e) {e.printStackTrace();}System.out.println("C");});Thread thread2 = new Thread(() -> {try {Thread.sleep(400);}catch (InterruptedException e) {e.printStackTrace();}System.out.println("B");});Thread thread3 = new Thread(() -> {try {Thread.sleep(600);}catch (InterruptedException e) {e.printStackTrace();}System.out.println("A");});thread1.start();thread2.start();thread3.start();thread1.join();thread2.join();thread3.join();}
}

在这个实例中,我们不需要使用synchronized锁来帮助我们控制进程,而是单纯通过每个线程的睡眠时间不同,利用时间差来实现规定的打印顺序;

这种方法虽然更加直观,但请注意,这种方法并不是线程同步的推荐做法,因为它依赖于硬编码的延迟,这可能会导致不可预测的行为,特别是在不同的系统或不同的负载条件下。通常,使用waitnotifyReentrantLockCondition来实现线程间的协调是更可靠和可控的方法。 

结论

理解wait()sleep()的区别对于编写高效的多线程程序至关重要。wait()sleep()都可以用来暂停线程的执行,但它们在锁状态、用途、中断响应等方面有着显著的不同。正确使用这些方法可以帮助你更好地控制线程的执行顺序和协作。

 


http://www.ppmy.cn/server/120616.html

相关文章

ARM驱动学习之9注册字符类设备

ARM驱动学习之9注册字符类设备 • 分配内存空间函数kmalloc – 分配连续的虚拟地址,用于小内存分配。在include/linux/slab.h文件中。 – 参数1:申请的内存大小(最大128K), – 参数2:GFP_KERNEL,代表优先权&#xff0…

09年408考研真题解析-计算机网络

[题34]在无噪声情况下,若某通信链路的带宽为3kHz,采用4个相位,每个相位具有4种振幅的QAM调制技术,则该通信链路的最大数据传输速率是(B) A.12 kbps B.24 kbps C.48 kbps D.96 kbps 解析&#xff…

C++ | Leetcode C++题解之第415题字符串相加

题目: 题解: class Solution { public:string addStrings(string num1, string num2) {int i num1.length() - 1, j num2.length() - 1, add 0;string ans "";while (i > 0 || j > 0 || add ! 0) {int x i > 0 ? num1[i] - 0 …

基于JAVA的居家办公OA系统

使用Spring Boot来搭建一个基础的居家办公OA系统的一部分——例如一个简单的任务管理模块。这个例子将包括创建一个任务的功能,并且能够将任务保存到数据库中。为了简化起见,这里我们只展示核心代码片段,并假设已经设置好了Spring Boot项目环…

.net 之内存回收

前言 一些基本概念如下: 托管代码 托管代码就是执行过程交由运行时管理的代码。 在这种情况下,相关的运行时称为公共语言运行时 (CLR),不管使用的是哪种实现(例如 Mono、.NET Framework 或 .NET Core/.NET 5)。 CLR 负责提取托…

TS React 项目中使用TypeScript

在 React 项目中使用 TS 创建新项目 在现有项目中添加 TS 创建新项目 命令:npx create-react-app my-app --template typescript 说明:在命令行中,添加 --template typescript 表示创建支持 TS 的项目 项目目录的变化: 在项目…

C语言:冒泡排序的注意事项及具体实现

一、注意事项 1、函数声明为:void bubble_sort(void* base, size_t num, size_t width, int (*cmp)(const void* e1, const void* e2)); 2、base 指向所要排序的数组 3、num 为数组的元素个数 4、width 为一个元素占多少个字节的空间 5、cmp 为函数指针,…

Java中stream流及Collectors的常见用法详细汇总!!!

目录 1. Stream流的优势 2. 常用用法 2.1 中间操作 2.1.1filter() 2.1.2 map() 2.1.3 sorted() 2.1.4 distinct() 2.1.5 limit() 2.1.6 skip() 2.2 终端操作 2.2.1 foreach() 2.2.2 collect() 2.2.3 reduce() 2.2.4 count() 2.2.5 anyMatch() 2.3 查找和匹配…