线程调度是指系统为线程分配处理器使用权的过程,主要调度方式有两种:分别是协同式线程调度和抢占式线程调度。
协同式调度:
线程的执行时间由线程本身来控制,线程把自己的工作执行完了之后,要主动通知系统切换到另外一个线程上。
协同式多线程最大的好处就是实现简单,而且由于线程要把自己的事情干完之后才会线程切换,切换操作对线程自己是可知的,没有什么线程同步的问题。
缺点是:线程执行时间不可控制,甚至如果一个线程编写有问题,一直不告知系统进行线程切换,会导致程序阻塞。
抢占式调度:
每个线程将由系统来分配执行时间,线程的切换不由线程本身来决定(java.yield()可以让出执行时间,但是要获取执行时间的话,线程本身是没什么办法的),在这种实现线程调度的方式下,线程的执行时间是系统可控的,也不会有一个线程导致整个进程阻塞的问题,java使用的线程调度方式就是抢占式调度。
虽然java线程调度是由系统自动完成的,但是可以设置线程优先级,来“建议”系统给某些线程多分配或少分配一些时间。java一共设置了10个线程优先级,两个线程都是Ready时,优先级越高的越容易被系统选择执行,(并不是说优先级越高的线程就一定比优先级低的线程先执行)。
线程状态:
线程状态一个有5种:
新建(New):创建后尚未启动的线程处于这种状态。
运行(Runable):Runable包括了操作系统线程状态中的Running和Ready,也就是此状态的线程有可能正在执行,也有可能等待着cpu在为它分配执行时间。
无限期等待(Waiting):处于这种状态的线程不会被分配cpu执行时间,他们要等待被其他线程显示的唤醒,以下方法会让线程进入无限期等待:
(1)没有设置Timeout参数的Object.wait()方法。
(2)没有设置Timeout参数的Thread.join()方法。
(3)LockSupport.park() 方法
限期等待(Timed Waiting):处于这种状态的线程也不会被分配cpu执行时间,不过无须等待被其他线程显示地唤醒,在一定时间之后它会被系统自动唤醒,以下方法会让线程进入限期等待状态:
(1)Thread.sleep()方法
(2)设置了Timeout参数的Object.wait()方法。
(3)设置了Timeout参数的Thread.join()方法。
(4)lockSupport.parkNanos()方法
(5)lockSupport.parkUntil()方法
阻塞(Blocked):线程被阻塞了,阻塞状态与等待状态的区别:阻塞状态在等待着获取一个排他锁,这个事件将在另外一个线程放弃这个锁的时候发生,而等待状态则是在等待一段时间,或者唤醒动作的发生。在程序等待进入同步区域的时候,线程会进入这种状态。
结束(Terminated):已终止的线程状态,线程已结束执行。
线程转换关系(不画图了,用箭头表示,蓝色表示经过的方法,改变线程状态):
New——(start())——>Running——(run()结束)——>Terminated
Waiting——(notify()或notifyAll())——>Running——(wait())——>Waiting
Running——(synchronized)——>Blocked————>Running
Running——(sleep())——>Timed Waiting————>Running