这节课我们来讲讲线程的调度算法。
首先给各位大哥预防针,这节课的内容偏理论,而且比较枯燥,但必须要懂。
首先说明一下,在操作系统调度线程的时候会准备一个就绪队列,处于就绪状态的线程就在这个就绪队列里排队,一旦处于运行状态的线程让出资源,就绪队列里的所有线程就会开始抢占资源,哪个线程能抢到资源是随机不固定的,另外,由于线程可以由运行状态转变为就绪状态,因此可能出现运行状态的程序在进入就绪状态后再一次抢得资源再次进入就绪状态。
下面介绍几种主流的线程调度算法:
- FIFO(First In First Out)/FIFS(First In First Service)
先进先出或者叫先来先服务(这个叫的更多),即就绪状态在就绪队列里排队,先进入就绪队列的线程先进入运行状态,直到该线程运行进入等待状态或结束状态后后面的线程才有机会进入运行状态。
- 时间片轮转
所有线程在就绪队列排队,先来的先进入运行状态,运行时间不得超过事先设定好的时间片(比如200ms),超过之后这个线程就会退出运行状态然后进入就绪队列的末尾。
- 时间片
和上面差不多,不过不轮转(即队列里所有线程一起竞争资源,不存在特定顺序)
- 优先级抢先
给线程设定优先级,只要就绪队列里存在优先级高的线程,优先级低的线程就不可能抢得到 资源进入运行状态。
Java里的线程调度算法是4+5:
不同优先级的线程在就绪队列里排队时,优先级高的先运行,且运行时间不得超过最大时间片,如果超过,则进入就绪队列再次与其他线程抢资源。
同等优先级的线程抢得资源的机会是均等的
如果优先级高的线程本来处于等待状态,在变成就绪状态进入就绪队列后当前正在运行的线程不会立刻让出资源,而是继续运行直到该线程运行时间超出最大时间片或该线程进入等待状态或停止状态。
Demo:
public class PriorityThreadTeach {
public static void main(String[] args) {
Thread thread1 = new DemoThread2("线程1");
Thread thread2 = new DemoThread2("线程2");
Thread thread3 = new DemoThread2("线程3");
//下面设置下优先级
thread1.setPriority(2);
thread2.setPriority(3);
thread3.setPriority(2);
thread1.start();
thread2.start();
thread3.start();
//可以看到线程1和线程2交替输出
/**
* 线程的priority属性值越小,优先级越高
* 由于线程1的优先级比线程2高,所以即使线程1主动让出资源进入就绪队列,也轮不到线程2进入运行状态
* 因为线程1在进入就绪队列后,就绪队列中存在比线程2优先级更高的线程(也就是线程1),
* 所以线程1不允许结束(因为没设置等待状态),永远轮不到 线程2运行
*
* 可以看到线程2先运行了一次,这是因为在线程1和线程3进入就绪队列之前线程2就已经进入运行状态了
* 所以即使优先级高的线程进入就绪队列,当前运行的线程并不会立即结束运行
*/
}
}
class DemoThread2 extends Thread{
public DemoThread2(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName());
yield(); //强制退出运行状态,进入就绪状态
}
}
}