论坛
潜水/灌水快乐,沉淀知识,认识更多同行。
ToB圈子
加入IT圈,遇到更多同好之人。
朋友圈
看朋友圈动态,了解ToB世界。
ToB门户
了解全球最新的ToB事件
博客
Blog
排行榜
Ranklist
文库
业界最专业的IT文库,上传资料也可以赚钱
下载
分享
Share
导读
Guide
相册
Album
记录
Doing
搜索
本版
文章
帖子
ToB圈子
用户
免费入驻
产品入驻
解决方案入驻
公司入驻
案例入驻
登录
·
注册
只需一步,快速开始
账号登录
立即注册
找回密码
用户名
Email
自动登录
找回密码
密码
登录
立即注册
首页
找靠谱产品
找解决方案
找靠谱公司
找案例
找对的人
专家智库
悬赏任务
圈子
SAAS
ToB企服应用市场:ToB评测及商务社交产业平台
»
论坛
›
软件与程序人生
›
后端开发
›
Java
›
面试记录
面试记录
滴水恩情
金牌会员
|
2022-8-28 06:50:40
|
显示全部楼层
|
阅读模式
楼主
主题
906
|
帖子
906
|
积分
2718
JVM线程属于用户态还是内核态
当进程运行在ring3级别时为用户态,ring0级别时为内核态
有些操作需要有内核权限才能进行,那么有三种由用户态切换到内核态的情况:
系统调用:操作系统封装内核指令,统一管理硬件资源,然后向用户程序提供系统服务,用户程序进行系统调用,操作系统进行检查确保安全然后再进行相应的资源访问操作。比如malloc(),print()调用write()系统输出字符串
异常事件:当cpu正在运行用户态程序,发生不可预知的异常事件,就会转用户态,比如缺页中断。
外围设备的中断:当外围设备完成请求就会向CPU发出中断信号,此时cpu暂停下一条要执行的指令,去执行中断信号所对应的程序
相同点和不同点:都是中断,但是系统调用是主动,其他都是被动
用户态和内核态线程的映射关系
一对一(内核线程实现)
程序使用轻量级进程和内核线程产生映射
缺点:轻量级进程的数量有限制,执行效率低
多对一(用户线程实现)
优点:用户线程数量几乎无限制,执行效率高
缺点:一个用户线程阻塞,其他线程也会阻塞
多对多
UT 用户态线程 LWP 轻量级线程 KLT 内核态线程
优点:
一个用户线程的阻塞不会导致所有线程的阻塞,因为此时还有别的内核线程被调度来执行。
多对多模型对用户线程的数量没有限制。
在多处理器的操作系统中,多对多模型的线程也能得到一定的性能提升,但提升的幅度不如一对一模型的高。在现在流行的操作系统中,大都采用多对多的模型。
用户态线程:切换代价小,高并发但是容易阻塞
内核态线程:处理能力高,切换代价大
Java线程的实现
虚拟机规范中并没有限定java线程需要使用哪种线程模型,要根据不同的平台来说,但是无论使用哪种线程模型,java程序的编码和运行都是没有差异的
Java线程调度
线程调度有两种:协同调度和抢占调度
协同:自己分配时间,自己切换
抢占:系统分配时间,系统决定线程的切换
java线程采用抢占调度
java线程的6种状态
新建———-运行———无限期等待——–限期等待———阻塞——结束
操作系统线程的几种状态
新建———就绪————等待————运行———–结束
java和操作系统的线程对应关系
1.2之前(绿色线程 1:N),程序员为jvm开发了一个线程调度内核,映射到操作系统层面就是用户态线程;
1.2(1:1)之后,jvmU型安泽了操作系统原生线程模型,映射到操作系统层面就是内核态线程,通过系统调用,将程序的线程交给了操作系统内核进行调度。
通过创建过程来理解
Java的Thread对象:仅仅是一个Java对象
JVM的JavaThread对象:连接着java的Thread对象与OS对象
JVM的OSThread对象:一个工具类,对OS线程
API
进行了功能性封装
流程图:
JVM_StartThread核心做了两件事情:
1.创建JavaThread对象
(1) 设置jvm执行run方法的跳板
(2) 调用os::create_thread创建OSThread对象及操作系统线程完成三者的关联
os::create_thread做了一下这些:
创建OSThread对象,将JavaThread对象与OSThread对象进行关联
线程库
为开发人员提供创建和管理线程的一套API
三个主要的线程库:
1)POSIX Pthreads:可以作为用户或内核库提供,作为 POSIX 标准的扩展
2)Win32 线程:用于 Window 操作系统的内核级线程库
3)Java 线程:Java 线程 API 通常采用宿主系统的线程库来实现,也就是说在 Win 系统上,Java 线程 API 通常采用 Win API 来实现,在 UNIX 类系统上,采用 Pthread 来实现。
操作系统对于锁的实现
在硬件层面,CPU提供了原子操作、关中断(可解决单核情况下两个线程同时获得锁)、锁内存总线的机制(解决多核情况下两个线程同时获得锁);OS基于这几个CPU硬件机制,就能够实现锁;再基于锁,就能够实现各种各样的同步机制(信号量、消息、Barrier等等等等)
synchronized的底层实现
是通过对象内部的一个监视器锁(monitor)实现的,监视器锁有时通过操作系统的互斥锁来实现的,而且现在主流的java虚拟机实现中,java的线程是映射到操作系统原生的内核线程中的,那么线程的阻塞或唤醒,就涉及到用户态和内核态的转换中,所以是重量级锁。
是一种块结构的同步语法,经过javac反编译之后,会在同步块的前后分别生成monitorenter和monitorexit两个字节码指令,这两个指令都需要一个reference类型的参数来指明加锁解锁的对象,如果synchronized明确了对象参数。就以这个对象的引用作为reference,如果没有指定,那就根据修饰的方法类型,来决定是区代码所在的对象实例还是相应的class对象。
反射的性能优化
两个地方导致性能差:getMethod和invoke,反射是一个解释操作,临时告诉jvm应该做什么
优化思路1:缓存Method,不重复调用getMethod
优化思路2:借助ASM框架,使用reflectAsm,让invoke变成直接调用
借反射的getDeclaredMethods获取目标类的所有方法,然后动态生成一个继承于MethodAccess 的子类SimpleBeanMethodAccess,动态生成一个Class文件并load到JVM中。
SimpleBeanMethodAccess中所有方法名建立index索引,index跟方法名是映射的,根据方法名获得index,SimpleBeanMethodAccess内部建立的switch直接分发执行相应的代码,这样methodAccess.invoke的时候,实际上是直接调用。
hashmap在jdk1.7的死循环
多线程头插法造成的,线程2已经完成扩容散列,链表变成了倒序,线程1再进行扩容,将倒序链表变成了一个正序链表,从而形成环形链表,在使用get方法时造成死循环。
常用集合
ArrayList
首先有三种构造方法(有参,无参,指定集合参数组成的列表)
主要就是三个方法:
1.ensureCapacityInternal得到最小扩容量,并进行扩容
2.ensureExplicitCapacity//判断是否需要扩容,如果最小扩容量大于数组现在的长度就调用grow方法
3.grow 进行位运算,扩容1.5倍,并进行判断是否超出数组的最大容量。
始化数据量为0,add时变为10,当 要 add 进第 1 个元素时,minCapacity 为 1,在 ensureCapacityInternal的Math.max()方法比较后,minCapacity 为 10 ,
最好在 add 大量元素之前用 ensureCapacity 方法(因为是public修饰),以减少增量重新分配的次数
Set Map
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
本帖子中包含更多资源
您需要
登录
才可以下载或查看,没有账号?
立即注册
x
回复
使用道具
举报
0 个回复
正序浏览
返回列表
快速回复
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
or
立即注册
本版积分规则
发表回复
回帖并转播
发新帖
回复
滴水恩情
金牌会员
这个人很懒什么都没写!
楼主热帖
体系集成商重返黄金年代
SFSafariViewController 加载的网页与 ...
ubuntu 20.04 安装好搜狗输入法无法输 ...
未来数据库需要关心的硬核创新 ...
nsenter命令简单介绍
Spark快速上手(2)Spark核心编程-RDD简 ...
【C++】STL——vector模拟实现
Linux 进程概念 (上)
一次服务器被入侵的处理过程分享 ...
Kali Linux全网最细安装教程
标签云
存储
挺好的
服务器
快速回复
返回顶部
返回列表