Java并发之Thread基础-3

Java Thread基础(3)

线程的实现

线程的实现主要有3种方式:

  • 使用内核线程实现;
  • 使用用户线程实现
  • 使用用户线程加轻量级进程混合实现。

内核线程就是直接由操作系统内核支持的线程,这类线程由内核来完成线程切换,内核通过调度器调度线程,并将线程的任务映射到各个处理器上。

轻量级进程是内核线程的一种高级接口——轻量级进程,轻量级进程就是通常意义上所说的线程,每个轻量级进程都由一个内核线程支持,这种轻量级进程与内核进程之间1:1的关系称为一对一线程模型。每个轻量级进程都是一个独立的调度单元,即使有一个轻量级进程在系统调用中被阻塞了,也不会影响整个进程。

轻量级进程有它的局限性:

  1. 基于内核线程实现,所以各种线程操作,如创建,析构和同步,都需要进行系统调用,这需要在用户态和内核态之间来回切换,代价较高。
  2. 每个轻量级进程都需要一个内核线程的支持,需要消耗一定的内核资源。因此,一个系统支持的轻量级进程的数量是有限的。

用户线程的广义定义是:一个线程只要不是内核线程,就可以认为是用户线程。所以,广义地说,轻量级进程也是用户线程。但是,轻量级进程的实现始终是建立在内核上的。

用户线程的狭义定义是指完全建立在用户空间上的线程库,系统内核不能感知线程存在的实现。用户线程的建立、同步、销毁和调度完全在用户态中完成,不需要内核的帮助。这种线程快速高效,常用于实现进程与线程的1:N关系。

用户线程的劣势在于没有内核的支持,所有的线程操作都需要自己实现,程序一般比较复杂。

用户线程加轻量级进程混合实现:将轻量级进程作为用户线程和内核线程之间的桥梁。

主流的操作系统都提供了线程实现,java 语言则提供了在不同硬件和操作系统平台下对线程操作的统一处理。每个执行了start()方法并且还未结束的Thread实例,都代表一个线程。Thread类中的关键方法大都是声明为Native(平台相关)的。

线程调度

线程调度的主要方式有2种:协同式线程调度和抢占式线程调度。

使用协同式线程调度的多线程系统,线程的执行时间由线程自身来控制,线程完成自身任务后,要主动通知系统切换到另外一个线程上。协同式系统的最大好处在于实现简单,且不存在线程同步问题。同样,坏处也很明显,如果一个线程有问题,一直不告知系统切换就会一直阻塞在那。使用抢占式调度的系统,线程由系统来分配时间,线程的切换不受自身控制。在这种情况下,不存在线程导致整个进程阻塞的情况,Java线程的调度方式就是抢占式调度。

线程的生命周期

Java 在枚举类Thread.State中定义了线程的几种状态:

  • NEW
    新建状态:线程刚刚创建,尚未启动。
  • RUNNABLE
    就绪状态:线程可执行,等待获取CPU使用权。
  • BLOCKED
    阻塞状态:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
  • WAITING
    等待状态:运行的线程执行wait(),join()LockSupport.park()方法,JVM会把该线程放入等待池中。当前线程在等待另一线程的特定动作。
  • TIMED_WAITING
    限时等待状态:运行的线程执行带时间参数wait(),带时间参数join(),sleep(),LockSupport.parkNanos()LockSupport.parkUntil()方法,JVM会把该线程放入等待池中。当前线程在等待另一线程的特定动作。
  • TERMINATED
    死亡状态:线程执行完成或者因异常退出,结束生命周期。

java线程状态迁移图

-------------本文结束感谢您的阅读-------------
坚持分享,您的支持将鼓励我继续创作!
0%