Java 与线程

来源:互联网 发布:misuo加密软件怎样 编辑:程序博客网 时间:2024/06/10 18:13

线程的实现:线程是比进程更轻量级的调度执行单位,各个线程既可以共享进程资源也可以独立调度,实现线程的主要方式有三种:使用内核线程实现,使用用户线程实现和使用内核线程加轻量级进程混合实现。

1.使用内核线程(KLT)实现,内核线程即直接由操作系统内核支持的线程,程序一般不会直接使用内核线程,而是使用内核线程的高级接口——轻量级进程(LWP),每个轻量级进程都有一个内核线程的支持,这种轻量级进程与内核线程之间的11关系成为一对一的线程模型。

 

 

轻量级进程由于使用内核线程实现,所以各种线程操作都需要进行系统调用,需要频繁的在用户态和内核态中来回切换,代价相对较高,其次由于每个轻量级进程都需要内核线程的支持,因此一个系统支持的轻量级进程的数量是有限的。

2.使用用户线程实现,狭义上的用户线程指,线程的建立、同步、销毁等操作都完全在用户态中完成,不需要内核的帮助,如果实现得当,这种线程不需要切换到内核态,因此操作可以是高效的和低消耗的,也可以支持规模更大的线程数量,这种进程与用户线程之间的1N关系称为一对多的线程模型。

 

 

使用用户线程的优势在于不需要系统内核的帮助,劣势也在于没有内核线程的支援。因为线程的创建、切换、调度等内核线程需要处理的问题在用户线程中也需要处理,一般很多的问题在用户线程中很难完成甚至不可能完成,现在使用用户线程的程序越来越少。

3.使用用户线程加轻量级进程混合实现,在这种混合实现方式下,既存在用户线程也存在内核线程,用户还是完全建立在用户空间中,线程的相关操作依旧廉价并且支持更大规模的用户线程并发,操作系统提供的轻量级进程则作为用户线程和内核线程之间的桥梁,用户线程的系统调用需要通过轻量级进程来实现,大大降低了整个进程被完全阻塞的风险。此种模式中用户线程与轻量级进程的数量比是不定的,即为NM的关系。

 

 

4.Java线程的实现:JDK1.2之前基于用户线程实现,1.2后基于操作系统原生线程模型实现。对Sun JDK来说,WindowsLinux版本都是使用一对一的线程模型来实现的,即一条用户线程映射到一条轻量级进程之中,因为WindowsLinux提供的都是一对一的线程模型。

 

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

协同式线程调度,线程执行时间有线程本身来控制,线程将本身的任务完成后通知系统切换到其他线程。好处为实现简单,没有线程同步问题。坏处也很明显:执行时间不可控,不稳定,一个线程的阻塞可能导致整个系统奔溃。

抢占式线程调度,每个线程由系统来分配执行时间,线程切换不由线程本身来决定(JavaThread.yield()可以让出执行时间但线程本身无法获取执行时间),这种线程调度方式下,线程执行时间是系统可控的一个线程的阻塞不会导致整个系统的奔溃。Java使用的线程调度方式即为抢占式调度。

Java语言支持通过设置线程优先级来为线程多分配或者少分配一点执行时间,Java语言共设置了10个级别的线程优先级,优先级月到的越容易被系统选择执行。

线程优先级并不是太靠谱,原因是Java的线程是通过映射到系统的原生的线程上来实现的,所以线程的最终调度最终还是取决于操作系统。我们不能在程序中通过优先级来准备的判断一组状态都为Ready的线程将会先执行哪一个。

 

线程状态转换:Java语言定义了五种线程状态,在任意一个时间点,一个线程只能有且只有其中的一种状态,5种状态分别如下:

  • 新建(New):创建后尚未启动的线程处于这种状态。
  • 运行(Runable):包括了操作系统线程状态中的RunningReady,处于此状态的线程可能正在运行,也有可能正在等待CPU分配执行时间。
  • 无限期等待(Waiting):这种状态的线程不会被分配CPU的执行时间,它们要等待被其它线程显示的唤醒。以下方法将会让线程陷入无限期的等待状态:

.没有设置Timeout参数的Object.wait()方法。

.没有设置Timeout参数的Thread.join()方法。

.LockSupport.park()方法。

  • 限期等待(Timed Waiting):不会被分配CPU执行时间,无须等待被其他线程显示唤醒,在一定时间后由系统自动唤醒,以下方法会让线程进入限期等待状态:

.Thread.sleep()

.设置了Timeout的参数的Object.wait()方法。

.设置了Timeout参数的Thread.join()方法。

.LockSupport.parkNanos()

.LockSupport.parkUntil()

  • 阻塞(Blocked):线程被阻塞,阻塞状态线程在等待获取一个排他锁,这个事件将在另一个线程放弃这个锁的时候发生,在程序等待进入同步区域的时候,线程将进入此种状态。
  • 结束(Terminated):已终止的线程状态,线程已经结束。

 

 

线程状态转换关系图



参考 《深入理解Java虚拟机》

0 0
原创粉丝点击