Java多线程的内存模型和Thread状态切换
线程的内存模型
32位操作系统的寻址空间为2的32次方,也就是4GB的寻址空间;系统在这4GB的空间里划分出1GB的空间给系统专用,称作内核空间,具有最高权限;剩下3GB的空间为用户空间(一般JVM的可用内存最大只能是2GB),只能访问当前线程划分的内存地址。用户线程需要访问硬件资源的时候需要委托内核线程进行访问,这就涉及到CPU上下文在用户模式和内核模式的切换。因此在使用线程或者进程的时候需要尽量避免不必要的用户模式和内核模式的切换。
进程是资源管理的最小单位,线程是CPU调度的最小单位。线程是比进程更轻量级的调度执行单位,线程可以共享同一个进程内的资源(内存地址、文件I/O等),又是CPI独立调度的基本单位。主要有三种实现线程的方法:
#1 使用一个内核线程支持一个用户进程,并且用户进程内支持多线程,优势在于线程的切换都发生在用户模式,劣势在于线程对于系统内核而言完全是透明的,所有资源调度需要用户进程进行处理,并且由于只有一个内核线程,所以只有一个CPU资源可以使用(多核CPU完全排不上用场),如果一个硬件I/O操作阻塞,所以的线程的硬件I/O都被阻塞。
#2 使用内核线程(Kernel Level Thread)一对一支持轻量级进程(Light Weight Process),一个轻量级进程对应一个线程,优势在于可以最大利用多CPU的性能,多任务同时进行,但最大劣势在于由于线程的阻塞或者唤醒都需要系统内核进行处理,所以程序需要不断在用户模式和内核模式之间切换,增加切换成本。
#3使用内核线程(Kernel Level Thread)一对一支持轻量级进程(Light Weight Process),并使用轻量级进程多对多支持用户线程,也就是混合使用前面两种实现的优势。这样上下文切换主要发生在用户模式,并且又可以依赖内核线程直接调用系统内核的功能。

线程的状态切换
Java多线程主要涉及到两种数据访问的同步,一种是heap中多线程可见的实例变量,一种是method area中的类成员变量,而method call stack中的数据是线程私有,则不需要进行同步协调。线程对象调用start方法之后就进入Ready状态等待线程调度器分配CPU资源进入Running,然后因为三种原因线程可能进入waiting/blocked状态:调用sleep/wait/suspend/join方法,调用了阻塞式IO方法,等待获取锁。

线程的Java编程接口
JDK自带开发包中支持两种线程的实现方式,extends Thread和implements Runnable,两种方式都是通过重写run()方法实现线程操作,唯一的区别在于前者限制了当前类不能再有其他业务上的继承父类。
public class App1 extends Thread {
@Override
public void run() {
super.run();
System.out.println(Thread.currentThread().getName() + " : start");
}
public static void main(String[] args) {
App1 thread = new App1();
thread.setName("App1 Thread");
thread.start();
System.out.println(Thread.currentThread().getName() + " : start");
}
}
public class App1 implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " : start");
}
public static void main(String[] args) {
Thread app1Thread = new Thread(new App1());
app1Thread.setName("App1 Thread");
app1Thread.start();
System.out.println(Thread.currentThread().getName() + " : start");
}
}
线程的启动方式:
#1 调用Thread.start()为异步实现,表示通知线程规划器指定的线程已经就绪,等待分配CPU资源并调用重写的run()方法,因此线程的执行具有不确定性;
#2 调用Thread.run()为同步实现,将不会获取任何线程相关的特性,而是简单的方法调用。
线程的退出方式:
#1 Thread.run()执行结束后线程正常退出。
#2 使用Thread.stop()强制退出(不推荐)
#3 使用Thread.interrupt()向线程发送需要结束的信号,但并不能立即停止线程,线程代码中需要调用Thread.interrupted()(或者是一个自定义的标志位)判断当前线程是否需要结束,从而手动控制线程的执行状态。
线程的优先级
通过Thread.setPriority(val)方法可以设置线程优先级,范围从1到10,线程调度器会将CPU资源尽量分给具有高优先级的线程,但并不意味着优先级高的线程总是能优先获取CPU资源;优先级具有继承性,子线程具有跟父线程同样的优先级。
死锁的产生和避免
Thread.suspend()和不指定超时时间的Object.wait()最容易产生死锁。利用JDK自带的工具jps可以监测线程是否已经进入死锁状态($ jps -l PID)。
Java多线程的内存模型和Thread状态切换的更多相关文章
- 【Java】JMM内存模型和JVM内存结构
JMM内存模型和JVM内存结构 JAVA内存模型(Java Memory Model) Java内存模型,一般指的是JDK 5 开始使用的新的内存模型,主要由JSR-133: JavaTM Memor ...
- Java多线程系列1 线程创建以及状态切换
我们知道线程线程有三种创建方式 1实现Runnable接口 2 继承Thread类 3使用Callable和Future接口创建线程.具体是创建Callable接口的实现类,并实现clall()方法. ...
- 黑马-----内存模型和volatile详解
黑马程序员:Java培训.Android培训.iOS培训..Net培训 JAVA线程-内存模型和volatile详解 一.单核内存模型 1.程序运行时,将临时数据存放到Cache中 2.将CPU计算所 ...
- Java内存模型和JVM内存管理
Java内存模型和JVM内存管理 一.Java内存模型: 1.主内存和工作内存(即是本地内存): Java内存模型的主要目标是定义程序中各个变量的访问规则,即在JVM中将变量存储到内存和从内存中取 ...
- 并发一:Java内存模型和Volatile
并发一:Java内存模型和Volatile 一.Java内存模型(JMM) Java内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和在内存中取出变量的底层细节,是围绕着 ...
- JVM内存结构、Java内存模型和Java对象模型
Java作为一种面向对象的,跨平台语言,其对象.内存等一直是比较难的知识点.而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚.比如本文要讨论的JVM内存结构.Java内存模型和Java对象模型 ...
- Java 内存模型和 JVM 内存结构真不是一回事
这两个概念估计有不少人会混淆,它们都可以说是 JVM 规范的一部分,但真不是一回事!它们描述和解决的是不同问题,简单来说, Java 内存模型,描述的是多线程允许的行为 JVM 内存结构,描述的是线程 ...
- JAVA内存模型和Happens-Before规则
前言 上一篇文章王子给大家介绍了并发编程中比较关心的三个核心问题,可见性.有序性和原子性. 今天我们继续来探索并发编程的内容,聊一聊JAVA的内存模型和Happens-Before规则. JAVA内存 ...
- java多线程03-----------------volatile内存语义
java多线程02-----------------volatile内存语义 volatile关键字是java虚拟机提供的最轻量级额的同步机制.由于volatile关键字与java内存模型相关,因此, ...
随机推荐
- 模板 - 动态规划 - 概率期望dp
https://blog.csdn.net/myjs999/article/details/81022546
- fzu2280 Magic(暴力+哈希预处理)
传送门 题意 q次操作,每次两种操作: 1 x y:将wx变成y 2 x:查询满足一下两个条件的字符串(①以字符串x为后缀②字符串值\(\le wx\)) 分析 对n个字符串预处理,设f[i][j]为 ...
- Hmz 的女装(递推)
Hmz 的女装 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Total Sub ...
- (二分图最大匹配)51NOD 2006 飞行员配对
第二次世界大战时期,英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2名飞行员,其中1名是英国飞行员,另1名是外籍飞行员.在众多的飞行员中, ...
- C#程序结构与基本语法
C# 程序结构 Hello World 实例 一个 C# 程序主要包括以下部分: 命名空间声明(Namespace declaration) 一个 class Class 方法 Class 属性 一个 ...
- Qt基本应用
1 使用方式 在qt designer中直接设计图形界面,然后使用pyGUI转换成py文件. 可以发现,转换的文件为一个class.并不是一个完整的程序(运行时无法出现窗口).这个类名字是Ui_Mai ...
- RHEL 6.5----Nginx负载均衡
实验环境 主机名 IP master 192.168.30.130 node-1 192.168.30.131 node-2 192.168.30.132 在master上安装 本次安装过程统一采用Y ...
- new操作符具体干了什么
function Func(){ }; var newFunc=new Func (); new共经过了4个阶段 1.创建一个空对象 var obj=new Object(); 2.设置原型链 把 o ...
- 找不到draw9patch.bat?已经不用找了
Google 已经因为 draw9patch 热门的原因,把它集成在 Android Studio 里面了, 你现在可以直接在 Android Studio 里直接打开编辑了.
- Xilinx HLS
Xilinx 的高层次综合(High Level Synthesis, HLS)技术是将C/C++/SystemC软件语言转换成Verilog或VHDL硬件描述语言的技术.现已应用在SDAccel,S ...