java中sleep方法和wait方法的五个区别

 更新时间:2022年05月09日 16:09:27   作者:​ Java中文社群   ​  
这篇文章主要介绍了java中sleep方法和wait方法的五个区别,sleep 方法和 wait 方法都是用来将线程进入休眠状态,但是又有一些区别,下面我们就一起来看看吧

前言:

sleep 方法和 wait 方法都是用来将线程进入休眠状态的,并且 sleep 和 wait 方法都可以响应 interrupt 中断,也就是线程在休眠的过程中,如果收到中断信号,都可以进行响应并中断,且都可以抛出 InterruptedException 异常,那 sleep 和 wait 有什么区别呢?接下来,我们一起来看。

区别一:语法使用不同

wait 方法必须配合synchronized 一起使用,不然在运行时就会抛出 IllegalMonitorStateException 的异常,如下代码所示: 

 初看代码好像没啥问题,编译器也没报错,然而当我们运行以上程序时就会发生如下错误: 

 而 sleep 可以单独使用,无需配合 synchronized 一起使用。

区别二:所属类不同

wait 方法属于 Object 类的方法,而 sleep 属于 Thread 类的方法,如下图所示: 

区别三:唤醒方式不同

sleep 方法必须要传递一个超时时间的参数,且过了超时时间之后,线程会自动唤醒。而 wait 方法可以不传递任何参数,不传递任何参数时表示永久休眠,直到另一个线程调用了 notify 或 notifyAll 之后,休眠的线程才能被唤醒。也就是说 sleep 方法具有主动唤醒功能,而不传递任何参数的 wait 方法只能被动的被唤醒

区别四:释放锁资源不同

wait 方法会主动的释放锁,而 sleep 方法则不会。接下来我们使用代码的方式来演示一下二者的区别。

sleep 不释放锁

接下来使用 sleep 是线程休眠 2s,然后在另一个线程中尝试获取公共锁,如果能够获取到锁,则说明 sleep 在休眠时会释放锁,反之则说明不会释放锁,实现代码如下:

public static void main(String[] args) throws InterruptedException {
    Object lock = new Object();
    new Thread(() -> {
        synchronized (lock) {
            System.out.println("新线程获取到锁:" + LocalDateTime.now());
            try {
                // 休眠 2s
                Thread.sleep(2000);
                System.out.println("新线程获释放锁:" + LocalDateTime.now());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }).start();
    // 等新线程先获得锁
    Thread.sleep(200);
    System.out.println("主线程尝试获取锁:" + LocalDateTime.now());
    // 在新线程休眠之后,尝试获取锁
    synchronized (lock) {
        System.out.println("主线程获取到锁:" + LocalDateTime.now());
    }
}

以上代码的执行结果如下图所示: 

 从上述结果可以看出,在调用了 sleep 之后,在主线程里尝试获取锁却没有成功,只有 sleep 执行完之后释放了锁,主线程才正常的得到了锁,这说明 sleep 在休眠时并不会释放锁。

wait 释放锁

接下来使用同样的方式,将 sleep 替换成 wait,在线程休眠之后,在另一个线程中尝试获取锁,实现代码如下:

public static void main(String[] args) throws InterruptedException {
    Object lock = new Object();
    new Thread(() -> {
        synchronized (lock) {
            System.out.println("新线程获取到锁:" + LocalDateTime.now());
            try {
                // 休眠 2s
                lock.wait(2000);
                System.out.println("新线程获释放锁:" + LocalDateTime.now());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }).start();
    // 等新线程先获得锁
    Thread.sleep(200);
    System.out.println("主线程尝试获取锁:" + LocalDateTime.now());
    // 在新线程休眠之后,尝试获取锁
    synchronized (lock) {
        System.out.println("主线程获取到锁:" + LocalDateTime.now());
    }
}

以上代码的执行结果如下图所示: 

 从上述结果可以看出,当调用了 wait 之后,主线程立马尝试获取锁成功了,这就说明 wait 休眠时是释放锁的。

区别五:线程进入状态不同

调用 sleep 方法线程会进入 TIMED_WAITING 有时限等待状态,而调用无参数的 wait 方法,线程会进入 WAITING 无时限等待状态 

代码演示:

public static void main(String[] args) throws InterruptedException {
    Object lock = new Object();
    Thread t1 = new Thread(() -> {
        synchronized (lock) {
            try {
                // 休眠 2s
                lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
    t1.start();

    Thread t2 = new Thread(() -> {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });
    t2.start();

    Thread.sleep(200);
    System.out.println("wait() 之后进入状态:" + t1.getState());
    System.out.println("sleep(2000) 之后进入状态:" + t2.getState());

}

以上代码的执行结果如下:

总结

sleep 和 wait 都可以让线程进入休眠状态,并且它们都可以响应 interrupt 中断,但二者的区别主要体现在:语法使用不同、所属类不同、唤醒方式不同、释放锁不同和线程进入的状态不同。​

到此这篇关于java中sleep方法和wait方法的五个区别的文章就介绍到这了,更多相关sleep 和wait方法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java接口返回json如何忽略特定属性

    Java接口返回json如何忽略特定属性

    这篇文章主要介绍了Java接口返回json如何忽略特定属性,通过SimplePropertyPreFilter方式(Json返回),这种写法,接口返回类型就要求是Json字符串类型,本文通过场景实例代码相结合给大家介绍的非常详细,需要的朋友可以参考下
    2022-09-09
  • Java8利用Stream实现列表去重的方法详解

    Java8利用Stream实现列表去重的方法详解

    这篇文章主要为大家介绍了Java利用Stream实现列表去重的几种方法详解,文中的示例代码讲解详细,需要的小伙伴可以参考一下
    2022-04-04
  • 解读@Data注解父子类继承的问题

    解读@Data注解父子类继承的问题

    在Java开发中,使用Lombok库的@Data注解简化了代码,但在父子类继承关系中使用@Data注解时会遇到问题,主要问题是:当父类和子类都使用@Data注解时,会导致equals方法不对称,解决方案是在子类中使用@EqualsAndHashCode注解
    2024-11-11
  • java以json格式向后台服务器接口发送请求的实例

    java以json格式向后台服务器接口发送请求的实例

    下面小编就为大家分享一篇java以json格式向后台服务器接口发送请求的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-01-01
  • Java多维数组详解

    Java多维数组详解

    大家好,本篇文章主要讲的是Java多维数组详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2021-12-12
  • 浅谈一下Java中的访问修饰符以及作用

    浅谈一下Java中的访问修饰符以及作用

    这篇文章主要介绍了浅谈一下Java中的访问修饰符以及作用,修饰符修饰的是“被访问”的权限,所有修饰符都可以修饰成员变量,方法,构造方法,需要的朋友可以参考下
    2023-05-05
  • Spring加载properties文件的方法

    Spring加载properties文件的方法

    这篇文章主要为大家详细介绍了Spring加载properties文件的两种方法,一是通过xml方式,另一种方式是通过注解方式,感兴趣的小伙伴们可以参考一下
    2016-06-06
  • JAVA正则表达式的基本使用教程

    JAVA正则表达式的基本使用教程

    这篇文章主要给大家介绍了关于JAVA正则表达式的基本使用教程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • 为什么说要慎用SpringBoot @ComponentScan

    为什么说要慎用SpringBoot @ComponentScan

    本文主要介绍了为什么说要慎用SpringBoot @ComponentScan,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2021-07-07
  • eclipse实现可认证的DH密钥交换协议

    eclipse实现可认证的DH密钥交换协议

    这篇文章主要介绍了eclipse实现可认证的DH密钥交换协议,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-06-06

最新评论