首页 理论教育 JAVA程序设计研究:线程调度

JAVA程序设计研究:线程调度

时间:2023-11-05 理论教育 版权反馈
【摘要】:线程的调度就是指按照特定的机制为多个线程分配CPU的使用权。处于运行期的线程会一直占用CPU,直到它不得不放弃CPU,这就是Java的线程调度机制。Java的线程不是分时调度的,同时启动多个线程后,不能保证各个线程轮流获得均等的CPU时间,代码范例3.2及其输出的结果可以证明这一点。第三种进行进程调度的方法是调用另一个线程的join()方法。

JAVA程序设计研究:线程调度

sleep()、yield()、join()的作用和区别如下。

这三个方法都是用于线程调度的,为了真正了解这三个方法的作用,必须首先深入了解Java的线程调度机制。

计算机只有一个CPU,在任意时刻只能执行一条机器指令,每个线程只有获得CPU的使用权才能执行指令。所谓多线程并发,其实是指从宏观上看,各个线程轮流获得CPU的使用权,分别执行各自的任务。线程的调度就是指按照特定的机制为多个线程分配CPU的使用权。目前有两种调度模型:分时调度模型和抢占式调度模型。

分时调度模型是指让所有线程轮流获得CPU的使用权,平均分配每个线程占用CPU的时间片。Java体系中使用的是第二种调度模型——抢占式调度模型,即优先让可运行池中优先级高的线程占用CPU,如果优先级都一样,可随便选择一个线程占用CPU。处于运行期的线程会一直占用CPU,直到它不得不放弃CPU,这就是Java的线程调度机制。

Java的线程不是分时调度的,同时启动多个线程后,不能保证各个线程轮流获得均等的CPU时间,代码范例3.2及其输出的结果可以证明这一点。

代码范例3.2:

上述代码的可能运行结果是:

由上面的结果可以看出,t1和t2使用CPU完全是随机的和任意的。如果希望明确一个线程给另外一个线程运行的机会,可以使用下面三个方法:

img让处于运行状态的线程调用Thread.sleep()方法。

img让处于运行状态的线程调用Thread.yield()方法。

img让处于运行状态的线程调用另一个线程的join()方法。

下面分别介绍这三种方法:

第一种Thread.sleep()方法是让线程睡眠,当一个线程在运行中执行了sleep()方法时,它就会放弃CPU,转到阻塞状态。如对代码范例3.2中的run()方法做如下修改。

代码范例3.3:

上述代码的可能结果是:(www.xing528.com)

假定某一时刻t1线程获得CPU,开始执行一次for循环,当它执行sleep()方法时,就会放弃CPU并开始睡眠。接着t2线程获得CPU,也开始执行一次for循环,当它执行sleep()方法时,就会放弃CPU并开始睡眠。假设此时t1线程已经结束睡眠,就会获得CPU,继续执行,依次循环。

第二种Thread.yield()方法进行进程调度。当线程在运行中执行了Thread类的yield()方法时,如果此时具有相同优先级的其他线程处于就绪状态,那么yield()方法将把当前运行的线程放到可运行池中并使另一个线程运行。如果没有相同优先级的可运行线程,那么yield()方法将什么也不做。如对代码范例3.1中的run方法做如下修改。

代码范例3.4:

上述代码的可能运行结果是:

通过对比结果可以得出结论。sleep()方法和yield()方法都是Thread类的静态方法,都会使当前处于运行状态的线程放弃CPU,把运行机会让给其他线程,两者的区别在于:

imgsleep()方法会给其他线程机会,而不考虑其他线程的优先级,因此会给较低优先级线程一个运行的机会;而yield()方法只会给相同优先级或者更高优先级的线程一个运行机会。

img线程执行sleep()方法后,将转到阻塞状态;而执行yield()方法后,会转到就绪状态。

imgsleep()方法有异常抛出,yield()方法则没有。

imgsleep()方法比yield()方法有更好的移植性,真实项目中很少使用yield()方法。

第三种进行进程调度的方法是调用另一个线程的join()方法。当前运行线程可以调用另一个线程的join()方法,当前线程转到阻塞状态,直到另一线程结束,它自己才能恢复运行。

代码范例3.5:

上述代码的运行结果为:

运行结果已经对join方法做出很好的解释了。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈