java面试突击之sleep和wait有什么区别详析

 更新时间:2022年02月23日 09:44:03   作者:Java中文社群  
按理来说sleep和wait本身就是八竿子打不着的两个东西,但是在实际使用中大家都喜欢拿他们来做比较,或许是因为它们都可以让线程处于阻塞状态,这篇文章主要给大家介绍了关于java面试突击之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区别的文章就介绍到这了,更多相关java sleep和wait区别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Mybatis创建逆向工程的步骤

    Mybatis创建逆向工程的步骤

    Mybatis逆向工程是一个自动生成Mybatis Mapper接口、XML文件和Java实体类的工具,可以提高开发效率,避免手动编写大量的重复代码,本文主要介绍了Mybatis创建逆向工程的步骤,感兴趣的可以了解一下
    2023-10-10
  • spring监视器actuator配置应用

    spring监视器actuator配置应用

    这篇文章主要介绍了spring监视器actuator配置应用,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-07-07
  • Mybatis generator的使用全面解析

    Mybatis generator的使用全面解析

    这篇文章主要介绍了Mybatis generator的使用,非常不错,具有参考借鉴价值,对mybatis generator的使用相关知识感兴趣的朋友一起学习吧
    2016-09-09
  • Java编写实现登陆窗口

    Java编写实现登陆窗口

    这篇文章主要为大家详细介绍了Java编写实现登陆窗口,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • SpringBoot之groups应对不同的Validation规则自定义方式

    SpringBoot之groups应对不同的Validation规则自定义方式

    这篇文章主要介绍了SpringBoot之groups应对不同的Validation规则自定义方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • java socket实现聊天室 java实现多人聊天功能

    java socket实现聊天室 java实现多人聊天功能

    这篇文章主要为大家详细介绍了java socket实现聊天室,java实现多人聊天功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-07-07
  • 浅谈线程的几种可用状态

    浅谈线程的几种可用状态

    下面小编就为大家带来一篇浅谈线程的几种可用状态。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • Maven通过filtering标签读取变量配置的三种方法

    Maven通过filtering标签读取变量配置的三种方法

    在日常开发中,我们大多都会有开发环境、测试环境、生产环境等,不同环境的参数肯定不一样,本文主要介绍了Maven通过filtering标签读取变量配置的三种方法,感兴趣的可以了解一下
    2024-03-03
  • Java中性能优化的35种方法汇总

    Java中性能优化的35种方法汇总

    很多同学在日常写Java的时候很少去关心性能问题,但是在我们写代码的过程中必须考虑到性能对程序的影响。小到我们使用位运算来实现算术运算,大到我们对 Java 代码的总体架构设计,性能其实离我们很近。本文介绍了Java中性能优化的35种方法,需要的朋友可以参考下。
    2017-01-01
  • java中this的用法示例(关键字this)

    java中this的用法示例(关键字this)

    这篇文章主要介绍了java中this的用法示例(关键字this),需要的朋友可以参考下
    2014-03-03

最新评论