Java线程模型、线程状态 - 线程(1)

1. 概述

众所周知,线程 - Thread 是比进程 - Progress 更轻量级的调度单位。简单来说,引入线程带来的好处是:

可以把一个进程资源分配执行调度分开,各个线程 既可以共享进程 资源(内存地址、文件I/O等),又可以独立调度。

线程实现方式:

主流的操作系统都实现了线程 ,而编程语言一般会提供关于线程 的统一API操作。那么,编程语言如何去调用系统线程 呢?这方面主要有3种方式:

  1. 使用内核线程 - Kernel Thread

    一对一线程模型 ,这个最重要,下面详细讲。

  2. 使用用户线程 - User Thread。

    一对N线程模型 ,用户程序完全模拟线程的行为,编码时操作的线程是用户程序模拟的线程,操作系统内核不能感知你做了创建、调度等等线程操作。许多编程语言最初使用过这种方式,但现在基本放弃了这种。

  3. 使用用户线程 + 轻量级进程混合实现。

    N对M线程模型 ,也有很多语言使用混合实现。

2. Java线程模型

  1. JVM线程模型的选择:

    首先,JVM规范没有限定JVM要使用哪种线程模型,具体的JVM采用什么线程模型与很多因素包括所在的OS有关;

    其次,线程模型只对线程的并发规模和操作成本产生影响。

    所以,线程模型对于我们程序员编码来说是透明的。

  2. SUN JDK中:

    对于官方JDK来说,因为Windwos和Linux操作系统(主流)只提供一对一线程模型 ,所以SUN JDK采用了一对一线程模型 。其它JDK可以有不同实现(如Solaris JDK可以采用N对M模型)。

  3. 内核线程方式:

    如上所述的三中方式中,SUN JDK采用的内核线程 。这种方式的线程调度流程如下:

    调度流程:

    1. 首先,从OS方面来说:如果操作系统内核中包括了一个线程调度器(Scheduler) ,内核可以操作调度器对内核线程 进行调度,将线程任务映射到各个CPU上。那么,这样的内核就叫多线程内核
    2. 其次,从程序来说:应用程序不能直接使用内核线程,只能去使用内核线程的一种高级接口 - 轻量级进程(LWP) 。对于编程语言来说,它们操作的实际上是这个LWP,LWP就是此时就可以被叫线程
    3. 最后,轻量级进程线程 之间的映射关系是1:1的,所以,这种方式叫做一对一线程模型

3. Java线程调度

线程调度是指系统为线程分配处理器使用权的过程,主要的调度方式有两种:

  1. 协同式线程调度(Cooperative Threads-Scheduling)

    这种方式是原始方式,由一个线程执行完通知另一个线程。已经很少使用,很容易造成阻塞。

  2. 抢占式线程调度(Preemptive Threads-Scheduling)

    主流方式,由系统来根据一系列复杂的规则为每个线程分配执行时间,线程的切换不是由线程自己做主(Java可以有Thread.yield()来让出执行时间,但是没有获取执行时间的方式)。

虽然抢占式调度是系统自动完成的,但是我们可以给出“建议”,即通过设置线程的优先 - priority

  1. Java语言有10个级别的线程优先级,其实在代码中就是1 - 10 十个int常量(默认5),通过setPriority(int x)来设置。
  2. 但是不要依赖优先级,因为它并不靠谱,最终结果仍取决于OS。仅举一例,比如Java有10种优先级,而Windows只提供了7种,那它们怎么可能一一对应呢?

所以,不要太依赖优先级。

请注意,抢占式调度总体来说是绝对由OS内核来决定的,程序只能使用“祈使语句”,即使是放弃使用CPU。

比如,Thread.yield(int x);中这么说:

A hint to the scheduler that the current thread is willing to yield its current use of a processor. The scheduler is free to ignore this hint.


4. 线程状态及状体转换

1. Java语言规范定义了如下6种线程状态:

  1. New - 新建

    创建后,尚未启动的线程

  2. Runable - 可运行
    1. 正在JVM中执行的线程处于这种状态(注意不是在CPU中执行,见2)
    2. Runable对应了两种OS线程状态Running和Ready,也就说Runable状态的Java线程有可能正在执行,也有可能正在等待CPU为它分配执行时间
  3. Blocked - 阻塞的

    其它线程占有的监视器的锁,此线程等待着进入同步区域的时候(等待获取锁),线程处于这种状态

  4. Waiting - 无限期等待

    处于监视器所属对象的wait set中,等待着被其它(此对象监视器所有者)线程唤醒。调用如下方法会时当前线程进入Waiting状态:

    • obj.wait()/obj.wait(0)方法
    • threadObj.join()/threadObj.join(0)方法
    • LockSupport.park()方法
  5. Timed Waiting - 期限等待

    在一定时间内会被系统自动唤醒,当然也会被唤醒。调用如下方法会让线程进入期限等待状态:

    • threadObj.sleep(n)方法
    • threadObj.join(n)方法
    • LockSupport.parkNanos(obj ,n)方法
    • LockSupport.parkUntil(obj ,n)方法
  6. Terminated

    已经终止的线程处于这种状态

2. 状态转换如下

需要注意的是,这些状态并不一定能通过线程的Thread.getState();方法来获取。不如,一个Waiting中的进程它肯定做不出getState()动作。



《Java线程和线程同步 - 线程(2)》

《Java线程模型、线程状态 - 线程(3)》



参考文献:

[ 1 ] 周志明.深入理解Java虚拟机[M].第2版.北京:机械工业出版社,2015.8.

[ 2 ] James Gosling,Bill Joy,Guy Steele,Gilad Bracha,Alex Buckley.The Java? Language Specification . Java SE 8 Edition . 英文版[EB/OL].2015-02-13.

时间: 2024-10-06 10:29:34

Java线程模型、线程状态 - 线程(1)的相关文章

更加强健的线程模型,解决线程卡死,退出异常情况

线程模型 1 package net.sz; 2 3 import java.util.Random; 4 import java.util.concurrent.ConcurrentLinkedQueue; 5 import org.apache.log4j.Logger; 6 7 /** 8 * 9 * <br> 10 * author 失足程序员<br> 11 * mail [email protected]<br> 12 * phone 13882122019&

Java内存模型与线程

写在前面:与之前主流程序语言(c/c++等)直接使用物理硬件和操作系统的内存模型不同,java虚拟机为了屏蔽各种硬件和操作系统的内存访问差异定义了一种java内存模型.其主要定义程序中各个变量的访问规则(在虚拟机中将变量存储到内存和从内存中取出变量的底层细节). 线程.主内存.工作内存之间的交互关系 1.java内存模型结构: -所有的变量都存储在主内存中. -每条线程还有自己的工作内存. -工作内存中保存了从主内存中拷贝的该线程所要使用到的变量 -每条线程对变量的操作必须在自己的工作内存中,不

Java内存模型与Java线程的实现原理

硬件的效率与一致性 基于高速缓存的存储交互很好的解决了处理器和内存的速度矛盾,但是也为计算机系统带来了更高的复杂度,因为它引入了一个新的问题:缓存一致性. 在多处理器系统中,每个处理器都有自己的高速缓存,而他们又共享同一主内存(Main Memory),如上图所示.当多个处理器的运算任务都涉及到主内存中的同一块区域,那么将高速缓存中的数据同步回主内存时,到底以谁的缓存数据为准呢?为了保证数据的一致性,需要各个处理器访问缓存时都遵循一些协议,即缓存一致性协议. Java内存模型 Java虚拟机规范

JVM——java内存模型和线程

概述 计算机的运算速度与它的存储和通信子系统速度的差距太大,大量的时间都花费在磁盘I/O.网络通信或者数据库访问上.我们当然不希望处理器大部分时间都处于等待其他资源的状态,要通过一些“手段”去把处理器的运算能力“压榨”出来,不然太浪费了. 衡量一个服务性能的高低好坏,每秒事务处理数(Transactions Per Second,TPS)是最重要的指标之一.代表一秒服务端平均能响应的请求总数,而TPS值与程序的并发能力又有密切的相关. 硬件的效率与一致性 处理器要和内存交互(取运算数据.存储运算

java并发之如何解决线程安全问题

并发(concurrency)一个并不陌生的词,简单来说,就是cpu在同一时刻执行多个任务. 而Java并发则由多线程实现的. 在jvm的世界里,线程就像不相干的平行空间,串行在虚拟机中.(当然这是比较笼统的说法,线程之间是可以交互的,他们也不一定是串行.) 多线程的存在就是压榨cpu,提高程序性能,还能减少一定的设计复杂度(用现实的时间思维设计程序). 这么说来似乎线程就是传说中的银弹了,可事实告诉我们真正的银弹并不存在. 多线程会引出很多难以避免的问题, 如死锁,脏数据,线程管理的额外开销,

Linux 线程实现机制分析 Linux 线程实现机制分析 Linux 线程模型的比较:LinuxThreads 和 NPTL

Linux 线程实现机制分析 Linux 线程实现机制分析  Linux 线程模型的比较:LinuxThreads 和 NPTL http://www.ibm.com/developerworks/cn/linux/kernel/l-thread/ 自从多线程编程的概念出现在 Linux 中以来,Linux 多线应用的发展总是与两个问题脱不开干系:兼容性.效率.本文从线程模型入手,通过分析目前 Linux 平台上最流行的 LinuxThreads 线程库的实现及其不足,描述了 Linux 社区是

【原创】Dubbo 2.7.5在线程模型上的优化

这是why技术的第30篇原创文章 这可能是全网第一篇解析Dubbo 2.7.5里程碑版本中的改进点之一:客户端线程模型优化的文章. 先劝退:文本共计8190字,54张图.阅读之前需要对Dubbo相关知识点有一定的基础.内容比较硬核,劝君谨慎阅读. 读不下去不要紧,我写的真的很辛苦的,帮忙拉到最后点个赞吧. 本文目录 第一节:官方发布 本小节主要是通过官方发布的一篇名为<Dubbo 发布里程碑版本,性能提升30%>的文章作为引子,引出本文所要分享的内容:客户端线程模型优化. 第二节:官网上的介绍

线程模型的综述

本文首先介绍了一些线程基础,比如并发.并行.内存分配.系统调用.POSIX线程.接着通过strace分析了线程与进程的区别.最后以Android.Golang等线程模型进行了分析. 基础 1. 什么是并发(Concurrent),什么是并行(Parallels)? 并发指同时进行多个计算任务. 并行指通过切换时间片模拟进行多个计算任务. 详细可以参考Difference between concurrent programming and parallel programming - stack

操作系统学习笔记----进程/线程模型----Coursera课程笔记

操作系统学习笔记----进程/线程模型----Coursera课程笔记 进程/线程模型 0. 概述 0.1 进程模型 多道程序设计 进程的概念.进程控制块 进程状态及转换.进程队列 进程控制----进程创建.撤销.阻塞.唤醒.... 0.2 线程模型 为什么引入线程 线程的组成 线程机制的实现 用户级线程.核心级线程.混合方式 1. 进程的基本概念 1.1 多道程序设计 允许多个程序同时进入内存运行,目的是为了提高CPU系统效率 1.2 并发环境与并发程序 并发环境: 一段时间间隔内,单处理器上