赣州新闻网

首页 / 科技

马龙:建立工业互联网服务能力的构想

2020-02-14 · 赣州新闻网 · 科技

Object中的wait、notify、notifyAll,可以用于线程间的通信,核心原理为借助于监视器的入口集与等待集逻辑

通过这三个方法完成线程在指定锁(监视器)上的等待与唤醒,这三个方法是以锁(监视器)为中心的通信方法

除了它们之外,还有用于线程调度、控制的方法,他们是sleep、yield、jH @ 5 F V % Soin方法,他们可以用于线程的协作,他们是围绕着线程的调度而来的

sleep方法

有两个版本的sleep方法,看得出来,核心仍旧是native方法

非native方法只是进行了参数校验,接着仍旧是调用I K 4的native方法,这个情形与wait是类似的

面试官问我:能说出多线程中 sleep、yield、join的用法及区别吗

接下来仔细看下,natH B F Pive版本的sleep

在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确b A j 1 T & E _ S性的影响。该线程不丢失任何监视器的所属权。

注意:

sleep不会释放锁,不会释放锁,不会释放j ~ y L $ G锁,可以理解为他进入监视器这个房间之后,在这房间里面睡着了

与wait类似的是,sleep也是可中断方法(从方法签名可以看得出来,可能抛出InterruptedException),也就是说如果一个线程正在sleM { 8 8 W Sep,如果另外的线程将他中断(调用interrupt方法),将会抛出异常,并且中断状态将会擦除

所以对于sleep方法,要么自己醒来,要么被中断后也会醒来。扩展:多线程基础体系知识清单

对于sleep始终有一个超时时间的设置,所以,尽管他是在监视u & O x I 3 n器内睡着了,但是并不会导致死锁,因为他终究是要醒来的

如下,线程休眠500毫秒,主线程S T E i50毫秒打印一次状态

ps:sleep方法的调用结果为状态:TIMED_WAITING

面试官问我:能说出多线程中 sleep、yield、join的用法及区别吗

借助于sleep方法,可以模拟线程的顺序执行

比如下面示例,两个阶段,第二个阶段将在第一个阶段执行之后才会执行

package test1;
import b I D C Jja} ] O e R 7 ) 9va.lang.Thread.State;
public class , x h 4 PT16 {
public static e 8 @;void main(String&nb` M s vsp;args)&N ? |nbsp;{
//模拟执行任务的第一个阶段的执行
Thread stb r R 3 AepOne Y I E v C L B | t= new Thread(() -> {
System.out.println(Thread.currentThread().getName(A ~ r b I ; H u E)+\" = N B ) ` = e p: 第一阶段任务开始执行\");
try {
Thread.sleep(1000);
System.oJ n ] O ( ? ! rut.println(Thre[ # P j ` w @ad.currentThread().getNamY @ 0 Ge()+\" : 第一阶段任务执行结束\");
} catch (InterruptedException e) {
}
}, \"firs/ G = $ S c q _tStage\");
stepOne.start();
//模拟任务第二个阶段的执行
Thread stepTwo = new T6 n 3 ` n nhread(() -> {
while (!State.TERMINATED.equav 4 Dls(stepOne.getState())) {
try {
Thread.X 6 s ?sleep(100);
System.ok - j 1 / [ b _ut.println(Thread.currentThread().getName()+\" : 我在等待第一阶段任务执行结束\");
} catch (InterruptedException e) {
}
}
System.out.println(Thread.currentThread().getName()+\" : 第二阶段任务执行结束\");
}, \"sk d r ^ LecondStO Z ~ . tage\");
stepTwo+ L / q i 4 O.start();
}
}
面试官问我:能说出多线程中 sleep、yield、join的用法及区别吗

另外,你应该已经注意到sleep方法都有static修饰7 f v % [ v E X,既然是静态方法,在Thread中的; ? 3 | )惯例就是针对于:当前线程,当前线程,. 1 k P {当前S B 6线程

yield方法

对于sleep或者wait方法,他们都将进入特定的状态,伴随着状态的切换,也就意味着等待某些条件的发生,才能够继续,比如条件满足,或者到时间等

但是yield方法不涉及这些事情,他针对的是时间片的划分与调度,所以对开发者来说只是临时让一下,让一下他又不会死,就只是再等等。

yield方法将会暂停当前正在执行的线程} V g m 对象,并执行其它线程,他始终都是RUNNABLE状态。

面试官问我:能说出多线程中 sleep、yield、join的用法及区别吗

不过要注 n I A s * q意,可以认为yield只^ 1 | G 1 ( )是一种建议性的,如果调用了yield方法,对CPU时间片的分配进行了“礼让1 { 5 c : v _ =”,它仍旧5 u - ! n有可能继续获得时间片,并且继续执行

所以一次调用yield 并不一定会I E Y s代表肯定会发N ` b | A K - J生什么

面试官问我:能说出多线程中 sleep、yield、join的用法及区别吗

借助于while循环以及yield方法,可以看得出来,也能一定程度上达到线程排序等待的效果

面试官问我:能说出多线程中 sleep、yield、join的用法及区别吗

yield也是静态方法,所以,也是针对于当前线程,当前线程,当前线程。扩展:多线程基础体系知识清单

join方法E F m

三个版本: z ? D v . #的join方法

面试官问我:能说出多线程中 sleep、yield、join的用法及区别吗

方法的实现过程,与. 7 c v v W r Vwait. 3 J也是非常类似f 3 3 , w 9,下面两个版本的方法一个调用join(0),一个参数校验后,调用join(millis),所以根本还是单参数版本的join方法

面试官问我:能说出多线程中 sleep、yield、join的用法及区别吗

在方法深入介绍前先2 o b 9 d看个例子

一个线程& ! 只要那个线程还活着+ 9 p ) K (,那么就会持续等待(或者有限时长)

线程终止之后会调用自身this.notifyAll,以通知在其上等待的线程

简单说,只要他活着大家就都等着, 他死了会通知,i C N 1 I ;所以7 t j D |效果就是在哪里调用了谁的join. C 2 $ 6 ; ?,哪里就要等待这个线程结束,才能继续

为什么要在start之后?

面试官问我:能说出多线程中 sleep、yield、join的用法及区别吗

如上面所示,将join改造成同步代码块如下所示,如果这段V ] & ] P n =同步代码在starte v e m 3 }方法之前

看下结果,没有等待指定线程结束,main主线` - F 2 : ^ 8程就结束了

面试官问我:能说出多线程中 sleep、yield、join的用法及区别吗

因为如果还没有调用start方法,那么isAlive是false(已U C N : O J S y开始未结束),主线程根本就不会等待,所以继续执行,然后继续到下面的start,然后主线程结束

所以,为什么join方法一| * R = z : g定要在start之前?

就是因为这个: - 2 O { # c 2isAlive方法的校验,你^ I 8 R h N l 7 0没有start,isAlive就是false,就不N P D 8 k V m A !会F P M ^ c 8 ` h同步l I 3等待,所以必须要先start,然后才能join

小结:

对于joi4 W mn方法,有两个关键:

  • 调用的哪个对象的join?
  • 在哪里调用的& ( E ^ ( i?

换一个说法:

join的效果是:一个线程等待另一个线程(直到结束或者持续一段时间)才执行,那么谁等待谁?

在哪个线程调用,哪个线程就会等待;调用的哪G 5 x { j W个Thread对象,就会等待哪个线程结束;

状态图回顾

在回顾下之前状态一文中的切换图,又了解了这几个方@ * B 6 C !法后,应该对状态切换有了更全面的认识

面试官问我:能说出多线程中 sleep、yield、join的用法及区别吗

总结

对于yield方法,比较容易理解,只是简单地对于CPU时间片的“礼让”,除非循环y] f 0 9 l : Jield,否则一次yield,可能下次该线程仍旧Z _ V q可能会抢占到CPU时间片,可能方法调用和不调用没差别

sleep是静态方法,针对当前线程,进入休K b -眠状态,两个版本的sleep方法始终有时间参数,所以必然会在指定的时间内苏醒,他也不会释放锁,当然,sleep方法的调用非必须在同步方法(同步代码块)内

join是实例方法,表示等待谁,是用于c a F线程顺序! 6 r ; {的调度方法,可以做到一个线程等待另外一个线程,join有三个版本,指定超时时间或者持续等待直到目标线程执行结束,join也无需在同步S = ` l方法(同步代码块)内

sleep和join都是可中断方法,被其他线程中断时,都会抛出InterruptedException异常U L d =,并且会醒来

join方法底层依赖waX o v X M = 3 Git,我们对比F ^ w下wait与sleep

  • wait8 D L F 4 | & g和sleep都会使线程进] e T F ~ B入阻塞状态,都是可中断方法,- d n 4 ( k被中断后都会抛出异常
  • wait是Object的方法,sleep是Thread的方法
  • wait必须在同w b ]步中执行,s} e P { , gleep不需要(join底层依赖wait,但是不需要在同步中,因为join方法就是synchronJ - T ! w oized的)
  • wait会释放锁,sleep不会释放锁
  • wait(无超时设置的版本)会持续阻塞,必须等待唤醒,而sleep必然有超时,所以一定会自己醒来
  • wait 实例方法(Object),在对L ` B + Z L象上调用,表示在其上等待;sleep静态方法,当前线程

Java知音,专注于Java实用文章推送,不容错过!

来源:cnblogs.com/noteless/p/10443446.html

确保工作能力于都互联网建立工业工业互联网服务