Java每日一题之Thread的yield和join方法区别

  • 2020 年 2 月 13 日
  • 筆記

Java每日一题之Thread的yield和join方法区别

  • 1.Java线程调度的一点背景
  • 2.理解线程的优先权
  • 3.yield()方法
  • 4.join()方法

1.Java线程调度的一点背景

在各种各样的线程中,Java虚拟机必须实现一个有优先权的、基于优先级的调度程序。这意味着Java程序中的每一个线程被分配到一个优先权,使用定义好的范围内的一个正整数表示。优先级可以被开发者改变。即使线程已经运行了一定时间,Java虚拟机也不会改变其优先级。 优先级的值很重要,因为Java虚拟机和下层的操作系统之间的约定是操作系统必须选择有最高优先权的Java线程运行。所以我们说Java实现了一个基于优先权的调度程序。该调度程序使用一种有优先权的方式实现,这意味着当一个有更高优先权的线程到来时,无论低优先级的线程是否在运行,都会中断(抢占)它。这个约定对于操作系统来说并不总是这样,这意味着操作系统有时可能会选择运行一个更低优先级的线程。 注意 : Java并不限定线程是以时间片运行,但是大多数操作系统却有这样的要求。在术语中经常引起混淆 :抢占经常与时间片混淆。事实上,抢占意味着只有拥有高优先级的线程可以优先于低优先级的线程执行,但是当线程拥有相同优先级的时候,他们不能相互抢占。它们通常受时间片管制,但这并不是Java的要求。

2.理解线程的优先权

接下来,理解线程优先级是多线程学习很重要的一步,尤其是了解yieid()函数的工作过程。

  1. 记住当线程的优先级没有指定时,所有线程都携带普通优先级。
  2. 优先级可以用从1到10的范围指定。10表示最高优先级,1表示最低优先级,5是普通优先级。
  3. 记住优先级最高的线程在执行时被给予优先。但是不能保证线程在启动时就进入运行状态。
  4. 与在线程池中等待运行机会的线程相比,当前正在运行的线程可能总是拥有更高的优先级。
  5. 由调度程序决定哪一个线程被执行。
  6. t.setPriority()用来设定线程的优先级。
  7. 记住在线程开始方法被调用之前,线程的优先级应该被设定。
  8. 你可以使用常量,如MIN_PRIORITY、MAX_PRIORITY、NORM_PRIORITY来设定优先级

3.yield()方法

理论上,yield意味着放手,放弃,投降。一个调用yield()方法的线程告诉虚拟机它乐意让其他线程占用自己的位置。这表明该线程没有在做一些紧急的事情。注意,这仅是一个暗示,并不能保证不会产生任何影响。 在Thread.java中yield()定义重要的几点 :

  1. Yield是一个静态的原生(native)方法。
  2. Yield告诉当前正在执行的线程把运行机会交给线程池中拥有相同优先级的线程。
  3. Yield不能保证使得当前正在运行的线程迅速转换到可运行的状态。
  4. 它仅能使一个线程从运行状态转到可运行状态,而不是等待或阻塞状态。

4.join()方法

把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。 比如在B线程中执行线程A的join方法,a.join(),那么B线程就会暂停执行,先等A线程执行完毕,B线程再重新进入可运行状态。join方法中还可以设置时间a.join(1000),这样就让A执行规定时间。在A线程执行过程中,如果还有其他线程,其他线程不受影响,会和A线程一起进行,知道A线程执行结束,B线程重新加入。