Java与线程

并发不一定依赖多线程(例如PHP的多进程并发),但是在Java里面讨论并发大多数和线程离不开。

线程是比进程更轻量级的调用执行单位,是CPU调度的基本单位。

线程的引入,可以把一个进程的资源分配和执行调度分开,各个线程共享资源,又可以独立调度。

相关:线程与进程

线程的实现

实现线程主要有3种方式:使用内核线程实现、使用用户线程实现和使用用户线程加轻量级进程混合实现。

使用内核线程实现

内核线程就是直接使用操作系统内核支持的线程,这种线程由内核完成线程切换,内核通过操纵调度器堆线程进行调度,并负责将线程的任务映射到各个处理器上。

程序一般不会直接去使用内核线程,而是使用内核线程的一种高级接口——轻量级进程(Light Weight Process, LWP),轻量级进程就是通常意义上所讲的线程。

每个轻量级进程都由一个内核线程支持。

基于内核线程实现的,系统调用代价相对较高,需要在用户态和内核态之间切换,一个系统支持轻量级进程的数量是有限的。

使用用户线程实现

用户线程指的是完全建立在用户空间的线程库上,系统内核不能感知线程存在的实现。
支持更大规模的线程数量,但是没有系统内核的支援,所有的线程操作都需要用户程序自己处理(一般都比较复杂)。

使用混合实现

使用户线程加轻量级进程的混合实现方式,用户线程还是完全建立在用户空间,而操作系统提供支持的轻量级进程则作为用户线程和内核线程之间的桥梁,这样可以使用内核提供的线程调用功能以及处理器映射。

将线程的调度等同于进程的调度,调度交由内核完成,而线程的创建、同步、销毁由核外线程库完成。

Java线程的实现

对于Sun JDK来说,它的Windows版和Linux版都是使用一对一的线程模型实现的,一条Java线程就映射到一条轻量级进程中。

Java线程调度

线程调度是指系统为线程分配处理器使用权的过程,主要调度方式有两种,分别是协同式线程调度和抢占式线程调度。

  • 协同式线程调度,线程的执行时间由线程本身控制,线程把自己的工作执行完了后,要主动通知系统切换到另一个线程上。
  • 抢占式线程调度,每个线程将由系统分配执行时间。

Java使用的是线程调度方式抢占式调度。

线程状态

Java语言定义了5种线程状态,在任意时间点,一个线程只能有且只有其中的一种状态。

  • 新建(New):创建后尚未启动的线程。
  • 运行(Runable):线程可能正在执行,也有可能等待CPU为它分配时间。
  • 无限期等待(Waiting):该状态下的线程不会被分配CPU执行时间,要等待被其他线程显示地唤醒。
  • 限期等待(Timed Waiting):该状态下的线程也不会被分配CPU执行时间,不过无须等待被其他线程显示地唤醒,在一定时间之后会由系统自动唤醒。
  • 阻塞(Blocked):阻塞状态下的线程在等待获取到一个排他锁,这个事件将在另外一个线程放弃这个锁的时候产生。
  • 结束(Terminated):已终止的线程状态。

阻塞状态是线程阻塞在进入synchronized关键字修饰的方法或代码块时的状态,但是阻塞在java.concurrent包中Lock接口的线程状态却是等待状态,因为java.concurrent包中Lock接口对于阻塞的实现均使用了LockSupport类中的相关方法。