线程调度是指系统为线程分配处理器使用权的过程。
一、线程调度方式
Java线程调度的方式主要有两种:协同式线程调度(Cooperative Threads-Scheduling)和抢占式线程调度(Preemptive Threads-Scheduling)。
1)协同式线程调度
使用协同式线程调度的多线程系统,线程的执行时间由线程本身控制,线程把自己的工作执行完后,要主动通知系统切换到另一个线程。
优点:
实现简单,没有线程同步问题
缺点:
线程执行时间不可控,可能出现长时间阻塞
2)抢占式线程调度
使用抢占式调度的多线程系统,每个线程将由系统来分配时间,线程的切换不由线程本身决定。
优点:
不会出现长时间阻塞的问题。
3)线程优先级
Java语言设置了10个级别的线程优先级,在两个线程同时处于Ready状态时,优先级高的线程更容易被系统选择执行。
由于Java线程是通过映射到操作系统原生线程上实现的,所以线程调度最终取决于操作系统。操作系统不见得能和Java线程优先级一一对应,如Windows中只有7种优先级。
另外在Windows中还存在“优先级推进器”(Priority Bossting),它的大致作用是当系统发现一个线程执行的“特别勤奋”时,可能会跨过优先级去为它分配执行时间。
因此,我们不能通过优先级来完全判断一组状态都为Ready的线程将会先执行哪一个。
二、线程状态
Java语言定义了5种线程状态,在任一时间点,一个线程只能有一种状态。
- 新建(New):创建后尚未启动该线程的状态
- 运行(Runable):包括了操作心痛线程状态中的Running和Ready,此状态的线程有可能在运行,也有可能在等待CPU分配执行时间
- 无限等待(Waiting):这种状态下的线程CPU不会为其分配时间,需要等待被其它线程唤醒,如:
- 没有设置Timeout参数的Object.wait()方法
- 没有设置Timeout参数的Thread.join()方法
- LockSupport.park()方法
- 限期等待(Timed Waiting): 这种状态下的线程CPU不会为其分配时间,但无需等待被唤醒,在一定时间后有系统唤醒,如:
- Thread.sleep()方法
- 设置了Timeout参数的Object.wait()方法
- 设置了Timeout参数的Thread.join()方法
- LockSupport.parkNanos()方法
- LockSupport.parkUntil()方法
- 阻塞(Blocked):线程被阻塞,等待获得排他锁,在另个一个线程放弃这个锁时发生
- 结束(Terminated):终止线程的线程状态,线程已执行结束
关于就绪队列、阻塞队列、挂起、激活等线程状态相关知识,请读者自行学习“操作系统”相关课程,不在这里赘述。