线程有以下三种实现方式
1、使用内核线程方式实现,优点内核完成线程切换和操纵调度器进行调度,并且负责将线程任务映射到处理器上。程序一般不使用内核线程会使用一种轻量级进程,轻量级进程与内核线程一对一模型如下图。
由于内核线程支持,一个轻量级进程在系统调用中阻塞了,不会影响进程继续工作。但是轻量级进程基于内核线程实现,所以创建、析构、同步都需要进行系统调用,系统调用的代价太高需要在用户态和内核态切换来去。其次轻量级进程都需要一个内核线程的支持,因此轻量级进程需要消耗一定的内核资源,因此一个系统可以支持的轻量级进程是有限的。
2、用户线程实现
完全建立在用户空间的线程。用户线程的创建、消毁、同步、调度完全在用户态中完成,不需要在内核态完成。优点非常快速且低消耗,也可以支持规模更大的数量,缺点没有内核线程的支援创建、切换和调度都是需要考虑的问题。操作系统只把资源分配给了进程,阻塞如何处理、多处理器系统如何将线程映射到处理器上会异常困难,甚至不可能完成
3、用户级线程和轻量级线程混合实现
用户线程创建还是建立在用户空间,因此用户线程的创建、析构、切换等操作依然廉价,所以可以支持大规模并发。操作系统提供支持的轻量级进程则用作用户线程和内核间的桥梁。这样可以使用内核线程的调度和处理器映射功能,并且系统调用通过轻量进程实现,大大降低整个进程阻塞的风险。
java的线程实现方式
主要调度方式有两种协同式调度和抢占式调度。协同式调度自己控制切换,把自己事情干完再进行线程切换。如果一个线程有问题,一直不告诉系统线程切换,就会阻塞程序。抢占式调度,多个线程由系统来分配运行时间,线程本身不决定线程切换,Thread。yield可以让出执行时间。
状态切换
新建:创建后尚未启动的状态
运行:操作系统中的running和ready,就是这个线程可能是运行状态也可能是等待cpu分配运行时间
无限期等待:不会被cpu分配运行时间,要等到其他线程显示的唤醒。没有设置timeout的object.wait(),Thread.join(),LockSupport.park()
限期等待:不会被cpu分配运行时间,不需要其他线程显示的唤醒。有设置timeout的object.wait(),Thread.join(),LockSupport.parkNanos(),Thread.sleep(),LockSupport.parkUtil();
阻塞状态:阻塞和等待的区别是阻塞在等待一个排它锁,这个事件将在其他线程是否锁是产生。线程等待进入同步区域后会阻塞。
结束:已经终止的线程状态。