点击上方 “ 布衣码农 ” ,免费订阅~选择“ 设为星标 ”,第一时间免费获得更新~

sleep方法
有两个版本的sleep方法,看得出来,核心仍旧是native方法。非native方法只是进行了参数校验,接着仍旧是调用的native方法,这个情形与wait是类似的

package test1;import java.lang.Thread.State;public class T16 {public static void main(String[] args) { //模拟执行任务的第一个阶段的执行 Thread stepOne = new Thread(() -> { System.out.println(Thread.currentThread().getName()+" : 第一阶段任务开始执行"); try { Thread.sleep(1000); System.out.println(Thread.currentThread().getName()+" : 第一阶段任务执行结束"); } catch (InterruptedException e) { } }, "firstStage"); stepOne.start(); //模拟任务第二个阶段的执行 Thread stepTwo = new Thread(() -> { while (!State.TERMINATED.equals(stepOne.getState())) { try { Thread.sleep(100); System.out.println(Thread.currentThread().getName()+" : 我在等待第一阶段任务执行结束"); } catch (InterruptedException e) { } } System.out.println(Thread.currentThread().getName()+" : 第二阶段任务执行结束"); }, "secondStage"); stepTwo.start(); }}

yield方法
对于sleep或者wait方法,他们都将进入特定的状态,伴随着状态的切换,也就意味着等待某些条件的发生,才能够继续,比如条件满足,或者到时间等。但是yield方法不涉及这些事情,他针对的是时间片的划分与调度,所以对开发者来说只是临时让一下,让一下他又不会死,就只是再等等yield方法将会暂停当前正在执行的线程对象,并执行其他线程,他始终都是RUNNABLE状态


join方法
三个版本的join方法





while (isAlive()) { wait(0); }
而这个wait(0)就相当于是this.wait(0),this就是我们自己创建的那个线程thread,看看方法的签名是不是有一个synchronized。isAlive()也是this.isAlive(),也就是如果当前线程alive(已经启动,但是未终止),那么将持续等待,等待的临界资源就是我们创建的这个线程对象本身。所以这两行代码的含义就是:该线程是否还存活?如果存活,调用join的那个线程将会在这个对象上进行等待(进入该线程对象的等待集)也就是说调用一个线程的join方法,就是在这个线程是等待,这个线程对象就是我们的锁对象(不要疑惑,Object都可以作为锁,Thread实例对象怎么不可以?)肯定大家很奇怪,既然是等待,wait又不会自己醒来,那不是出问题了吗?其实线程结束后,会调用this.notifyAll,所以主线程main会被唤醒如果传递的参数不为0,将会走到下面的分支,会wait指定时长,与上面的逻辑一致,只不过是有指定超时时长而已 long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base;
手动版本的等待结束只是将join方法换成了同步代码块,锁对象为那个线程的实例对象thread,调用他的wait方法从结果上看,效果一样(不过此处没有持续监测isAlive(),所以一旦主线程醒来,即使线程没有结束,也会继续,不能百分百确保main肯定等待线程结束)



调用的哪个对象的join?
在哪里调用的?
状态图回顾
在回顾下之前状态一文中的切换图,又了解了这几个方法后,应该对状态切换有了更全面的认识
总结
对于yield方法,比较容易理解,只是简单地对于CPU时间片的“礼让”,除非循环yield,否则一次yield,可能下次该线程仍旧可能会抢占到CPU时间片,可能方法调用和不调用没差别。sleep是静态方法,针对当前线程,进入休眠状态,两个版本的sleep方法始终有时间参数,所以必然会在指定的时间内苏醒,他也不会释放锁,当然,sleep方法的调用不是必须在同步方法(同步代码块)内。join是实例方法,表示等待谁,是用于线程顺序的调度方法,可以做到一个线程等待另外一个线程,join有三个版本,指定超时时间或者持续等待直到目标线程执行结束,join也无需在同步方法(同步代码块)内。sleep和join都是可中断方法,被其他线程中断时,都会抛出InterruptedException异常,并且会醒来join方法底层依赖wait,我们对比下wait与sleepwait和sleep都会使线程进入阻塞状态,都是可中断方法,被中断后都会抛出异常
wait是Object的方法,sleep是Thread的方法
wait必须在同步中执行,sleep不需要(join底层依赖wait,但是不需要在同步中,因为join方法就是synchronized的)
wait会释放锁,sleep不会释放锁
wait(无超时设置的版本)会持续阻塞,必须等待唤醒,而sleep必然有超时,所以一定会自己醒来
wait 实例方法(Object),在对象上调用,表示在其上等待;sleep静态方法,当前线程
··················END··················
注:非技术讲解配图均来源于网络
期待分享
如果对你有用
可以点个 「在看」 或者分享到 「 朋友圈 」 哦
你「在看」吗?
↓↓