Java与线程

1. 线程的实现

三种方式

1. 使用内核线程实现

内核线程的定义:内核线程(Kernel-Level Thread简称KLT)是由操作系统内核支持的线程。线程的创建、销毁、调度都有内核完成。
一般程序是不会直接使用内核线程的,而是使用一种叫做轻量级进程(Light Weight Process简称LWT),这种东西就是我们上面通俗说的线程的概念。

每一个轻量级进程都由一个内核线程支持,它们是一一对应的关系。即线程创建、销毁、调度都是由内核线程完成的。


image.png
  • 优点:线程的创建、销毁、调度都由内核来完成,简单。
  • 缺点:线程的创建、销毁都要陷入内核态来完成,用户态和内核态的切换是很耗时的。
2. 使用用户线程实现

用户线程的意思是指线程的所有资源都由程序库实现,系统内核不感知用户线程的存在。

  • 优点:线程的创建、销毁等操作都是在用户态实现的,所以效率很高。
  • 缺点:线程的调度、线程的阻塞方式等等一系列的问题都要由程序库自己实现,太繁琐太复杂。一般由于硬件设施的不同,想要适配所有设施几乎不可能实现。
3. 使用内核线程和用户线程的混合实现

即同时存在内核线程和用户线程,在这种混合实现中,用户线程的创建、销毁等操作都还是在用户态完成,效率很高。而内核线程的调度等操作依旧由系统内核来完成。只需要维护一个关系:用户线程--内核线程的映射关系即可。

一般这种映射关系维持在多对多的情况下:


image.png

许多Unix系统比如Solaris/HP-UX都提供了这种线程模型

4. Java线程的选择

不同的操作系统支持不同的线程模型。
在Windows和Linux下,Java使用的是一对一的内核线程实现。

2. 线程的调度

调度一般分为两种:协调式调度和抢占式调度。

协调式

每个线程都会在执行完自己的所有指令后才会让出CPU。

  • 缺点很明显,如果一个线程时间很长或者有问题,则它也不会让出CPU,导致整个系统阻塞。
抢占式
  • 每个线程运行的时间有操作系统决定,线程本身无法决定。
    这种方式很好解决了协调式的问题,不会因为某个线程有问题而导致整个系统阻塞。
  • 抢占式还提供了线程的优先级设置,但这个不可信,只是一个参考。操作系统自己可以修改线程的优先级,所以即使设置线程的优先级,最后执行的时候也不一定真的有效。

2. 线程的状态

Java线程的状态有五种,即任一一个线程在一个时刻只会存在下面状态的一种。


image.png
  • 新建(New)
    创建后未启动的状态
  • 运行(Running)
    包括正在运行的和就绪的(即没有阻塞等待CPU分配时间)。
  • 无限等待
    这种状态的线程只能被其他线程唤醒,自己不会自己苏醒过来。
  • 有限等待
    这种状态的线程过了一段时间后,自己会自动苏醒过来。
  • 阻塞
    这种状态的线程因为某个互斥锁而被阻塞,当互斥锁被释放后,这种线程就会唤醒。
  • 结束
    已终止的线程。
  • 总结一下
    其实这里只是Java对线程的状态划分而已,没什么特别的。

你可能感兴趣的:(Java与线程)