在多线程编程中,线程的执行顺序并不由开发者直接控制,而是由 线程调度器(Scheduler) 决定。调度策略直接影响程序的并发表现与性能。Java 中,线程调度主要依赖 时间片轮转 与 优先级机制。
一、时间片轮转(Time Slicing)
-
概念:操作系统为每个线程分配一段 CPU 时间片,时间片用完后线程进入就绪队列,等待下次调度。
-
特点:
- 公平性:所有线程都有机会执行。
- 切换频繁:保证系统响应性,但会增加上下文切换开销。
-
Java 中表现 :
Thread.sleep()
可以人为让出 CPU,从而体现时间片切换效果。
示例:
java
public class TimeSliceDemo {
public static void main(String[] args) {
Runnable task = () -> {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " 执行");
try { Thread.sleep(100); } catch (InterruptedException e) {}
}
};
new Thread(task, "线程A").start();
new Thread(task, "线程B").start();
}
}
结果中,A 和 B 线程会交替输出,体现时间片轮转。
二、优先级机制(Thread Priority)
-
概念:线程拥有优先级(1~10,默认 5),调度器通常会优先选择高优先级线程执行。
-
特点:
- 优先级并非绝对保证,只是"更倾向"。
- 不同操作系统对优先级调度支持程度不同。
-
Java API:
javathread.setPriority(Thread.MAX_PRIORITY); // 10 thread.setPriority(Thread.MIN_PRIORITY); // 1 thread.setPriority(Thread.NORM_PRIORITY); // 5
示例:
java
public class PriorityDemo {
public static void main(String[] args) {
Runnable task = () -> {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName());
}
};
Thread t1 = new Thread(task, "低优先级");
Thread t2 = new Thread(task, "高优先级");
t1.setPriority(Thread.MIN_PRIORITY);
t2.setPriority(Thread.MAX_PRIORITY);
t1.start();
t2.start();
}
}
结果往往是"高优先级"线程输出更多,但不能保证绝对执行完毕。
三、时间片 vs 优先级:对比分析
调度策略 | 特点 | 适用场景 |
---|---|---|
时间片轮转 | 公平、均衡、响应快,但开销高 | 多线程计算、后台服务 |
优先级机制 | 高优先级更可能先执行,但无绝对保证 | 实时任务、关键线程抢占 CPU |
四、开发中的注意点
- 不可依赖优先级实现关键逻辑:不同系统实现差异大,不具备可移植性。
- 合理利用 sleep/yield:控制线程切换,更好体现时间片轮转效果。
- 核心逻辑避免依赖调度器:推荐使用线程池、任务队列来保证任务执行顺序。
五、总结
- Java 线程调度依赖 操作系统 ,调度策略主要有 时间片轮转 与 优先级机制。
- 时间片强调公平性,优先级强调倾向性。
- 在实际开发中,调度策略不可控,不能依赖它保证业务逻辑,正确做法是 借助并发工具类(Executor、Lock、Semaphore 等)管理线程。