一张图搞清楚wait、sleep、join、yield四者区别,面试官直接被征服!

简介: 一张图搞清楚wait、sleep、join、yield四者区别,面试官直接被征服!

写在开头

在线程的生命周期中,不同状态之间切换时,可以通过调用sleep()、wait()、join()、yield()等方法进行线程状态控制,针对这一部分知识点,面试官们也会做做文章,比如问你这些方法的作用以及之间的区别。

那么今天我们就一起来总结一下这几个方法的作用及区别,先画一个思维导图梳理一下,便于理解与记忆,争取在被问到这个点时彻底征服面试官!(图片可保存常看哈
image.png

sleep()

sleep()是Thread类中的一个静态本地方法,通过设置方法中的时间参数,使调用它的线程休眠指定时间,线程从RUNNING状态转为BLOCKED状态,这个过程中会释放CPU资源,给其他线程运行机会时不考虑线程的优先级,但如果有同步锁则sleep不会释放锁即其他线程无法获得同步锁,需要注意的是sleep()使用时要处理异常。休眠时间未到时,可通过调用interrupt()方法来唤醒休眠线程。

【代码示例1】

try {
   //sleep会发生异常要显示处理
    Thread.sleep(20);//暂停20毫秒
} catch (InterruptedException e) {
   
    e.printStackTrace();
}

为什么sleep()放在Thread类中

答:因为sleep是线程级别的休眠,不涉及到对象类,只是让当前线程暂停,进入休眠状态,并不释放同步锁资源,也不需要去获得对象锁。

wait()

wait() 是Object类的成员本地方法,会让持有对象锁的线程释放锁,进入线程等待池中等待被再次唤醒(notify随机唤醒,notifyAll全部唤醒,线程结束自动唤醒)即放入锁池中竞争同步锁,同时释放CPU资源,它的调用必须在同步方法或同步代码块中执行,也需要捕获 InterruptedException 异常。

【代码示例2】

//同步代码块
 synchronized (obj) {
   
     System.out.println("obj to wait on RunnableImpl1");
     try {
   
         obj.wait();
     } catch (InterruptedException e) {
   
         e.printStackTrace();
     }
     System.out.println("obj continue to run on RunnableImpl1");
 }

为什么wait()是Object的方法

答:每个对象都拥有对象锁,wait的作用是释放当前线程所占有的对象锁,自然是要操作对应的Object而不是Thread,因此wait要放入到Object中。

join()

join()同样是Thread中的一个方法,调用join的线程拥有优先使用CPU时间片的权利,其他线程需要等待join()调用线程执行结束后才能继续执行,探索其底层会发现,它的底层是通过wait()进行实现,因此它也需要处理异常。

【代码示例3】

//创建TestRunnable类
TestRunnable mr = new TestRunnable();
//创建Thread类的有参构造,并设置线程名
Thread t1 = new Thread(mr, "t1");
Thread t2 = new Thread(mr, "t2");
Thread t3 = new Thread(mr, "t3");
//启动线程
t1.start();
try {
   
    t1.join(); //等待t1执行完才会轮到t2,t3抢
} catch (InterruptedException e) {
   
    e.printStackTrace();
}
t2.start();
t3.start();

我们跟进join()方法内部会发现,其底层主要通过wait()实现,其中参数代表等待当前线程最多执行 millis 毫秒,如果 millis 为 0,则会一直执行,直至完成,其他线程才会继续向下;

【源码示例1】

    public final synchronized void join(long millis)
    throws InterruptedException {
   
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
   
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
   
            while (isAlive()) {
   
                wait(0);
            }
        } else {
   
            while (isAlive()) {
   
                long delay = millis - now;
                if (delay <= 0) {
   
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

yield()

yield()是Thread的一个静态方法,它的调用不需要传入时间参数,并且yield() 方法只会给相同优先级或更高优先级的线程运行的机会,并且调用yield的线程状态会转为就绪状态,调用yield方法只是一个建议,告诉线程调度器我的工作已经做的差不多了,可以让别的线程使用CPU了,没有任何机制保证采纳。所以可能它刚让出CPU时间片,又被线程调度器分配了一个时间片继续执行了。使用时不需要处理异常。

【代码示例4】

public class Test {
   

    public static void main(String[] args) {
   
        Thread thread1 = new Thread(Test::printNumbers, "小明");
        Thread thread2 = new Thread(Test::printNumbers, "小华");
        thread1.start();
        thread2.start();
    }
    private static void printNumbers() {
   
        for (int i = 1; i <= 5; i++) {
   
            System.out.println(Thread.currentThread().getName() + ": " + i);

            // 当 i 是偶数时,当前线程暂停执行
            if (i % 2 == 0) {
   
                System.out.println(Thread.currentThread().getName() + " 让出控制权...");
                Thread.yield();
            }
        }
    }
}

输出:

小明: 1
小华: 1
小华: 2
小明: 2
小明 让出控制权...
小华 让出控制权...
小明: 3
小明: 4
小明 让出控制权...
小明: 5
小华: 3
小华: 4
小华 让出控制权...
小华: 5

总结

上文中,我们结合代码示例,对这个四个方法进行了详细介绍,下面我们以sleep()为参照,进行对比总结:

(1)sleep()与wait()的区别?

  1. sleep() 是 Thread 类的静态本地方法;wait() 是Object类的成员本地方法;
  2. JDK1.8 sleep() wait() 均需要捕获 InterruptedException 异常;
  3. sleep() 方法可以在任何地方使用;wait() 方法则只能在同步方法或同步代码块中使用;
  4. sleep() 会休眠当前线程指定时间,释放 CPU 资源,不释放对象锁,休眠时间到自动苏醒继续执行;wait() 方法放弃持有的对象锁,进入等待队列,当该对象被调用 notify() / notifyAll() 方法后才有机会竞争获取对象锁,进入运行状态。

(2)sleep()与yield()的区别?

  1. sleep() 方法给其他线程运行机会时不考虑线程的优先级;yield() 方法只会给相同优先级或更高优先级的线程运行的机会;
  2. sleep() 方法声明抛出 InterruptedException;yield() 方法没有声明抛出异常;
  3. 线程执行 sleep() 方法后进入超时等待状态;线程执行 yield() 方法转入就绪状态,可能马上又得得到执行;
  4. sleep() 方法需要指定时间参数;yield() 方法出让 CPU 的执行权时间由 JVM 控制。

(3)sleep()与join()的区别?

  1. JDK1.8 sleep() join() 均需要捕获 InterruptedException 异常;
  2. sleep()是Thread的静态本地方法,join()是Thread的普通方法;
  3. sleep()不会释放锁资源,join()底层是wait方法,会释放锁。

结尾彩蛋

如果本篇博客对您有一定的帮助,大家记得留言+点赞+收藏呀。原创不易,转载请联系Build哥!

目录
相关文章
|
2月前
|
Java 程序员 调度
Java 高级面试技巧:yield() 与 sleep() 方法的使用场景和区别
本文详细解析了 Java 中 `Thread` 类的 `yield()` 和 `sleep()` 方法,解释了它们的作用、区别及为什么是静态方法。`yield()` 让当前线程释放 CPU 时间片,给其他同等优先级线程运行机会,但不保证暂停;`sleep()` 则让线程进入休眠状态,指定时间后继续执行。两者都是静态方法,因为它们影响线程调度机制而非单一线程行为。这些知识点在面试中常被提及,掌握它们有助于更好地应对多线程编程问题。
87 9
|
2月前
|
Java 程序员 开发者
面试官最爱的面试题:wait() 和 notify() 为什么需要同步?
大家好,我是小米。今天来探讨一个常见的Java面试题:为什么线程通信的 `wait()`、`notify()` 和 `notifyAll()` 方法被定义在 Object 类里,且必须在同步方法或同步块中调用?通过小明和小红的工作场景,我们理解了这些方法的核心思想——线程间的协调与通信。它们依赖于对象锁,确保线程按预期顺序执行,避免资源争抢和死锁。掌握这些知识点,能帮助你更好地应对多线程相关的面试问题。如果你对线程同步等话题感兴趣,欢迎继续交流。
60 12
|
2月前
|
编译器 Android开发 开发者
Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
Lambda表达式和匿名函数都是Kotlin中强大的特性,帮助开发者编写简洁而高效的代码。理解它们的区别和适用场景,有助于选择最合适的方式来解决问题。希望本文的详细讲解和示例能够帮助你在Kotlin开发中更好地运用这些特性。
42 9
|
2月前
|
安全 Java 程序员
Java面试必问!run() 和 start() 方法到底有啥区别?
在多线程编程中,run和 start方法常常让开发者感到困惑。为什么调用 start 才能启动线程,而直接调用 run只是普通方法调用?这篇文章将通过一个简单的例子,详细解析这两者的区别,帮助你在面试中脱颖而出,理解多线程背后的机制和原理。
78 12
|
3月前
|
Java 调度
|
3月前
|
Java
Java社招面试题:& 和 && 的区别,HR的套路险些让我翻车!
今日分享的主题是如何区分&和&&的区别,提高自身面试的能力。主要分为以下四部分。 1、自我面试经历 2、&amp和&amp&amp的不同之处 3、&对&&的不同用回答逻辑解释 4、彩蛋
|
3月前
|
Java 关系型数据库 数据库
京东面试:聊聊Spring事务?Spring事务的10种失效场景?加入型传播和嵌套型传播有什么区别?
45岁老架构师尼恩分享了Spring事务的核心知识点,包括事务的两种管理方式(编程式和声明式)、@Transactional注解的五大属性(transactionManager、propagation、isolation、timeout、readOnly、rollbackFor)、事务的七种传播行为、事务隔离级别及其与数据库隔离级别的关系,以及Spring事务的10种失效场景。尼恩还强调了面试中如何给出高质量答案,推荐阅读《尼恩Java面试宝典PDF》以提升面试表现。更多技术资料可在公众号【技术自由圈】获取。
|
4月前
|
Java 程序员
Java社招面试题:& 和 && 的区别,HR的套路险些让我翻车!
小米,29岁程序员,分享了一次面试经历,详细解析了Java中&和&&的区别及应用场景,展示了扎实的基础知识和良好的应变能力,最终成功获得Offer。
117 14
|
4月前
|
存储 缓存 网络协议
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点,GET、POST的区别,Cookie与Session
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点、状态码、报文格式,GET、POST的区别,DNS的解析过程、数字证书、Cookie与Session,对称加密和非对称加密
|
5月前
|
前端开发 小程序 JavaScript
面试官:px、em、rem、vw、rpx 之间有什么区别?
面试官:px、em、rem、vw、rpx 之间有什么区别?
125 0

热门文章

最新文章