Java线程调度
线程调度是指系统为线程分配处理器使用权的过程,调度主要方式有两种,分别是协同式 (Cooperative Threads-Scheduling)线程调度和抢占式(Preemptive Threads-Scheduling)线程调度。
如果使用协同式调度的多线程系统,线程的执行时间由线程本身来控制,线程把自己的工作执行完了之后,要主动通知系统切换到另外一个线程上去。协同式多线程的最大好处是实现简单,而且由于线程要把自己的事情干完后才会进行线程切换,切换操作对线程自己是可知的,所以一般没有什么线程同步的问题。
(坏处也很明显:线程执行时间不可控制,甚至如果一个线程的代码编写有问题,一直不告知系统进行线程切换,那么程序就会一直阻塞在那里)
如果使用抢占式调度的多线程系统,那么每个线程将由系统来分配执行时间,线程的切换不由线程本身来决定。譬如在Java中,有Thread::yield()方法可以主动让出执行时间,但是如果想要主动获取执行时间,线程本身是没有什么办法的。在这种实现线程调度的方式下,线程的执行时间是系统可控的,也不会有一个线程导致整个进程甚至整个系统阻塞的问题。Java使用的线程调度方式就是抢占式调度。
虽然说Java线程调度是系统自动完成的,但是我们仍然可以“建议”操作系统给某些线程多分配一点执行时间,另外的一些线程则可以少分配一点——这项操作是通过设置线程优先级来完成的。
不过,线程优先级并不是一项稳定的调节手段,很显然因为主流虚拟机上的Java线程是被映射到系统的原生线程上来实现的,所以线程调度最终还是由操作系统说了算。
Java线程优先级与Windows线程优先级之间的对应关系,Windows平台的虚拟机中使用了除
THREAD_PRIORITY_IDLE之外的其余6种线程优先级,因此在Windows下设置线程优先级为1和2、3
和4、6和7、8和9的效果是完全相同的。
线程优先级并不是一项稳定的调节手段,这不仅仅体现在某些操作系统上不同的优先级实际会变
得相同这一点上,还有其他情况让我们不能过于依赖线程优先级:优先级可能会被系统自行改变,例
如在Windows系统中存在一个叫“优先级推进器”的功能(Priority Boosting,当然它可以被关掉),大
致作用是当系统发现一个线程被执行得特别频繁时,可能会越过线程优先级去为它分配执行时间,从
而减少因为线程频繁切换而带来的性能损耗。因此,我们并不能在程序中通过优先级来完全准确判断
一组状态都为Ready的线程将会先执行哪一个。