Java中wait与sleep的区别讲解(wait有参及无参区别)

 更新时间:2022年04月13日 10:33:04   作者:Youcan.  
这篇文章主要介绍了Java中wait与sleep的讲解(wait有参及无参区别),通过代码介绍了wait() 与wait( long timeout ) 区别,wait(0) 与 sleep(0)区别,需要的朋友可以参考下

1. wait() 与wait( long timeout ) 区别

public class WaitDemo4 {
    public static void main(String[] args) {
        Object lock = new Object();
        Object lock2 = new Object();
        new Thread(() -> {
            System.out.println("线程1: 开始执行" + LocalDateTime.now());
            synchronized (lock) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程1: 执行完成" + LocalDateTime.now());
            }
        },"无参wait线程").start();
 
        new Thread(() -> {
            System.out.println("线程2: 开始执行" + LocalDateTime.now());
            synchronized (lock2) {
                try {
                    lock2.wait(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程2: 执行完成" + LocalDateTime.now());
            }
        },"有参wait线程").start();
    }
}
 
输出:
线程2: 开始执行2022-04-12T12:13:57.130
线程1: 开始执行2022-04-12T12:13:57.130
线程2: 执行完成2022-04-12T12:13:58.130

不同点:

1.wait( long timeout) :当线程超过了设置时间之后,自动恢复执行;而wait() 无线等待状态。

2. 使用无参的wait方法,线程会进入WAITING; 使用有参的wait方法,线程会进入TIMED_WAITING。

public class WaitDemo5 {
    public static void main(String[] args) {
        Object lock = new Object();
        Object lock2 = new Object();
        new Thread(() -> {
            synchronized (lock2) {
                System.out.println("线程2: 开始执行" + LocalDateTime.now());
                try {
                    lock2.wait(60 * 60 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程2: 执行完成" + LocalDateTime.now());
            }
        },"有参wait线程").start();
 
        new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (lock2) {
                System.out.println("唤醒线程2");
                lock2.notify();
            }
        }).start();
    }
}
输出:
线程2: 开始执行2022-04-12T12:28:23.200
唤醒线程2
线程2: 执行完成2022-04-12T12:28:24.169
public class WaitDemo6 {
    public static void main(String[] args) {
        Object lock = new Object();
 
        new Thread(() -> {
            System.out.println("线程1: 开始执行" + LocalDateTime.now());
            synchronized (lock) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程1: 执行完成" + LocalDateTime.now());
            }
        },"无参wait线程").start();
 
        new Thread(() -> {
            System.out.println("线程2: 开始执行" + LocalDateTime.now());
            synchronized (lock) {
                try {
                    lock.wait(60 * 60 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程2: 执行完成" + LocalDateTime.now());
            }
        },"有参wait线程").start();
 
        new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (lock) {
                System.out.println("唤醒所有线程");
                lock.notifyAll();
            }
        }).start();
    }
}
 
输出:
线程1: 开始执行2022-04-12T12:34:34.317
线程2: 开始执行2022-04-12T12:34:34.317
唤醒所有线程
线程2: 执行完成2022-04-12T12:34:35.295
线程1: 执行完成2022-04-12T12:34:35.295

共同点:

1. 无论是有参的wait方法还是无参的wait方法,它都可以使用当前线程进入休眠状态。

2.无论是有参的wait方法还是无参的wait方法,它都可以使用notify / ontifyAll进行唤醒。

2. wait(0) 与 sleep(0)区别

public class WaitSleepDemo7 {
    public static void main(String[] args) {
        Object lock = new Object();
        Thread t1 = new Thread(() -> {
            synchronized (lock) {
                System.out.println("线程1:开始执行");
                try {
                    lock.wait(0);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程1:执行结束");
            }
        },"wait(0)");
        t1.start();
 
        Thread t2 = new Thread(() -> {
            System.out.println("线程2:开始执行");
            try {
                Thread.sleep(0);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程2:执行结束");
        }, "sleep(0)");
        t2.start();
    }
}
输出:
线程1:开始执行
线程2:开始执行
线程2:执行结束

wait (0) : 无限期等待下去,相当于wait();

sleep(0) :相当于Thread.yeild() , 让出CPU执行权,重新调度,但是sleep(0) 会继续执行。

3. wait 和sleep 释放代码

wait 和 sleep 在有所的情况下的锁处理行为是完全不同的:

public class WaitSleepDemo8 {
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        Object lock2 = new Object();
        Thread t1 = new Thread(() -> {
            synchronized (lock) {
                System.out.println("线程1:开始执行");
                try {
                    lock.wait(3 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程1:结束执行");
            }
        }, "wait");
        t1.start();
 
        Thread t2 = new Thread(() -> {
            synchronized (lock2) {
                System.out.println("线程2:开始执行");
                try {
                    Thread.sleep(3 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程2:结束执行");
            }
        }, "sleep");
        t2.start();
 
        // 创建 2 个线程,先让线程休眠 1s 之后,尝试获取,看能不能获取到锁
        // 如果可以获取到锁,说明休眠时线程是释放锁的,而如果获取不到锁,说明是不释放锁
        Thread t3 = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("尝试获取 wait 方法的锁");
            synchronized (lock) {
                System.out.println("成功获取 wait 的锁");
            }
        }, "wait2");
        t3.start();
 
        Thread t4 = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(0);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("尝试获取 sleep 方法的锁");
            synchronized (lock2) {
                System.out.println("成功获取 sleep 的锁");
            }
        }, "sleep2");
        t4.start();
 
    }
}
输出:
线程1:开始执行
线程2:开始执行
尝试获取 sleep 方法的锁
尝试获取 wait 方法的锁
成功获取 wait 的锁
线程1:结束执行
线程2:结束执行
成功获取 sleep 的锁

wait方法(不管是有参还是无参)在执行的时候都会释放锁;而sleep 方法不会释放锁。

4. wait 与 sleep 区别

相同点:

1. 都是可以让线程进入休眠

2. 都可以响应Interrupt(中断)请求

不同点:

1. wait必须配合synchronized一起使用;而sleep不需要。

2. wait 属于Object(对象)的方法;而sleep属于Thread(线程)的方法。

3. sleep 不释放锁;而wait释放锁。

4. sleep 必须要传递一个数值类型的参数;而wait可以不传参。

5. sleep 让线程进入到TIMED_WAITING状态;而无参的wait方法让线程进入了WAITING状态。

6. 一般情况下,sleep只能等待超时时间之后再回复执行;而wait可以接受notify / notifiAll之后就绪执行。

(MS):

1.为什么 wait 释放锁⽽ sleep 不释放锁?

【JVM 强制语法检查,wait ⽅法默认等待⽆期限】

2.为什么 wait 要放在 Object 中?

【wait 使⽤要加锁,也就是要操作锁,锁是针对对象级别的⽽⾮线程级别的,线程和对象是⼀对多,所以 wait 最便利的⽅式是放在 Object 中】

到此这篇关于Java中wait与sleep的区别讲解(wait有参及无参区别)的文章就介绍到这了,更多相关java wait与sleep内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot3配置Logback日志滚动文件的方法

    SpringBoot3配置Logback日志滚动文件的方法

    本文介绍了在SpringBoot3中配置Logback日志滚动文件的方法,因为SpringBoot3内置的logback版本是1.4.14,之前使用SpringBoot2.1.5的logback配置发现有些东西不能生效了,需要的朋友可以参考下
    2024-08-08
  • java若依框架集成redis缓存详解

    java若依框架集成redis缓存详解

    今天小编就为大家分享一篇关于java若依框架集成redis缓存的实现,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2021-08-08
  • Java多线程中断机制三种方法及示例

    Java多线程中断机制三种方法及示例

    这篇文章主要介绍了Java多线程中断机制三种方法及示例,向大家分享了这三种方法的介绍几代码示例,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • Netty中解码器的作用及实现详解

    Netty中解码器的作用及实现详解

    这篇文章主要介绍了Netty中解码器的作用及实现详解,本章我们只需要让客户端发送消息的时候循环发送100次,服务端不变,看看服务端是不是接收到了100条消息,需要的朋友可以参考下
    2023-12-12
  • Java 项目中使用递归的小结

    Java 项目中使用递归的小结

    在 Java 中,递归是指在方法的定义中调用自身的过程,递归是基于方法调用栈的原理实现的:当一个方法被调用时,会在调用栈中创建一个对应的栈帧,包含方法的参数、局部变量和返回地址等信息,这篇文章主要介绍了Java 项目中对使用递归的理解分享,需要的朋友可以参考下
    2024-07-07
  • SpringCloud+SpringBoot项目搭建结构层次的实例

    SpringCloud+SpringBoot项目搭建结构层次的实例

    这篇文章详细介绍了SpringCloud项目的架构层次及其搭建经验,包括Controller层、Service层、Repository层、Entity层、DTO层、Exception层等,通过文字和图片的形式,帮助读者理解如何组织和实现一个SpringBoot项目的不同层次
    2025-01-01
  • java注解之运行时修改字段的注解值操作

    java注解之运行时修改字段的注解值操作

    这篇文章主要介绍了java注解之运行时修改字段的注解值操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • Java使用TCP套接字实现多人聊天功能详解

    Java使用TCP套接字实现多人聊天功能详解

    这篇文章主要介绍了Java使用TCP套接字实现多人聊天功能,结合实例形式详细分析了java使用socket通信实现tcp协议下的聊天功能客户端与服务器端相关实现技巧,需要的朋友可以参考下
    2019-10-10
  • java字节码框架ASM的深入学习

    java字节码框架ASM的深入学习

    这篇文章主要给大家介绍了java中字节码框架ASM的相关资料,文中介绍的非常详细,相信对大家的理解和学习具有一定的参考借鉴价值,有需要的朋友们下面来一起学习学习吧。
    2017-01-01
  • Java Mybatis框架增删查改与核心配置详解流程与用法

    Java Mybatis框架增删查改与核心配置详解流程与用法

    MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO为数据库中的记录
    2021-10-10

最新评论