JVM系统学习
2021-09-10 11:24:59 0 举报
AI智能生成
JVM系统学习
作者其他创作
大纲/内容
3.JUC多线程及并发包
1.谈谈你对volatile的理解
1.volatile是Java虚拟机提供的轻量级的同步机制
1.1保证可见性
1.2不保证原子性
1.3禁止指令重排
2.JMM你谈谈
2.1可见性
2.2原子性
number++在多线程下是非线程安全的,如何不加synchronized解决?
2.3VolatileDemo代码演示可见性+原子性代码
2.4有序性
重排1
重排2
案例
禁止指令重排小总结(了解)
3.你在哪些地方用到过volatile?
3.1 单例模式DCL代码
3.2代理模式volatile分析
2.CAS你知道吗
1.比较并交换
CASDemo
2.CAS底层原理?如果知道,谈谈你对UnSafe的理解
atomicInteger.getAndIncrement();
UnSafe
CAS是什么
unSafe.getAndIncrement
底层汇编
简单版小总结
3.CAS缺点
循环时间长开销很大
只能保证一个共享变量的原子性
引出来ABA问题???
3.原子类AtomicInteger的ABA问题谈谈?原子更新引用知道吗
ABA问题的产生
原子引用
AtomicReferenceDemo
时间戳原子引用
AtomicStampedReference
ABADemo
4.我们知道ArrayList是线程不安全,请编写一个不安全的案例并给出解决方案
解决方案1
ContainerNotSafeDemo
限制不可以使用vector和Collections工具类解决方案2
List线程copyOnWriteArrayList
set线程CopyOnwriteHashSet
map线程ConcurrentHashMap
5.公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解?请手写一个自旋锁
公平锁和非公平锁
是什么
两者的区别
题外话
可重入锁(又名递归锁)
是什么
ReentrantLock/synchronized就是一个典型的可重入锁
可重入锁最大的作用就是避免死锁
ReenterLockDemo
参考1
参考2
自旋锁
SpinLockDemo
独占锁(写)/共享锁(读)/互斥锁
ReadWriteLockDemo
读写锁
6.CountDownLatch/CyclicBarrier/Semaphore使用过吗?
CountDownLatch
让一些线程阻塞直到另外一些完成后才被唤醒
CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,调用线程会被阻塞.其他线程调用countDown方法计数器减1(调用countDown方法时线程不会阻塞),当计数器的值变为0,因调用await方法被阻塞的线程会被唤醒,继续执行
CountDownLatchDemo
关门案例
枚举的使用
秦灭六国
CyclicBarrier
CyclicBarrier的字面意思是可循环(Cyclic) 使用的屏障(barrier).它要做的事情是,让一组线程到达一个屏障(也可以叫做同步点)时被阻塞,知道最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活,线程进入屏障通过CyclicBarrier的await()方法.
CyclicBarrierDemo
集齐7颗龙珠就能召唤神龙
代码
Semaphore
信号量的主要用户两个目的,一个是用于多喝共享资源的相互排斥使用,另一个用于并发资源数的控制.
SemaphoreDemo
抢车位
代码
7.阻塞队列知道吗?
队列+阻塞队列
为什么用?有什么好处?
BlockingQueue的核心方法
架构梳理+种类分析
架构介绍
种类分析
ArrayBlockingQueue: 由数组结构组成的有界阻塞队列.
LinkedBlockingDeque: 由链表结构组成的有界(但大小默认值Integer>MAX_VALUE)阻塞队列.
PriorityBlockingQueue:支持优先级排序的无界阻塞队列.
DelayQueue: 使用优先级队列实现的延迟无界阻塞队列.
SynchronousQueue:不存储元素的阻塞队列,也即是单个元素的队列.
理论
SynchronousQueueDemo
LinkedTransferQueue:由链表结构组成的无界阻塞队列.
LinkedBlockingDeque:由了解结构组成的双向阻塞队列.
用在哪里
生产者消费者模式
传统版
ProdConsumerTraditionDemo
阻塞队列版
ProdConsumerBlockQueueDemo
线程池
消息中间件
8.线程池用过吗?ThreadPoolExecutor谈谈你的理解?
为什么使用线程池,优势
线程池如何使用?
架构实现
编码实现
了解
Executors.newCachedThreadPool();
java8新出
Executors.newWorkStealingPool(int);
java8新增,使用目前机器上可以的处理器作为他的并行级别
重点
Executors.newFixedThreadPool(int)
执行一个长期的任务,性能好很多
Executors.newSingleThreadExecutor()
一个任务一个线程执行的任务场景
Executors.newCachedThreadPool()
适用:执行很多短期异步的小程序或者负载较轻的服务器
ThreadPoolExecutor
线程池几个重要参数介绍?
7大参数
1.corePoolSize:线程池中的常驻核心线程数
2.maximumPoolSize:线程池能够容纳同时执行的最大线程数,此值大于等于1
3.keepAliveTime:多余的空闲线程存活时间,当空间时间达到keepAliveTime值时,多余的线程会被销毁直到只剩下corePoolSize个线程为止
4.unit:keepAliveTime的单位
5.workQueue:任务队列,被提交但尚未被执行的任务.
6.threadFactory:表示生成线程池中工作线程的线程工厂,用户创建新线程,一般用默认即可
7.handler:拒绝策略,表示当线程队列满了并且工作线程大于等于线程池的最大显示 数(maxnumPoolSize)时如何来拒绝.
说说线程池的底层工作原理?
9.线程池用过吗?生产上你是如何设置合理参数
线程池的拒绝策略请你谈谈
是什么
JDK内置的拒绝策略
AbortPolicy(默认):直接抛出RejectedException异常阻止系统正常运行
CallerRunPolicy:"调用者运行"一种调节机制,该策略既不会抛弃任务,也不会抛出异常,而是
DiscardOldestPolicy:抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交
DiscardPolicy:直接丢弃任务,不予任何处理也不抛出异常.如果允许任务丢失,这是最好的拒绝策略
以上内置策略均实现了RejectExecutionHandler接口
你在工作中单一的/固定数的/可变你的三种创建线程池的方法,你用哪个多?超级大坑
答案是一个都不用,我们生产上只能使用自定义的
Executors中JDK给你提供了为什么不用?
你在工作中是如何创建线程池的,是否自定义过线程池使用
Case
合理配置线程池你是如何考虑的?
CPU密集型
IO密集型
1
2
10.死锁编码及定位分析
是什么
产生死锁的主要原因
系统资源不足
进程运行推进的顺序不合适
资源分配不当
代码
解决
jps命令定位进程编号
jstack找到死锁查看
11.Java里面锁请谈谈你的理解,能说多少说多少
4.JVM+GC解析
前提复习
JVM内存结构
jVM体系概述
Java8以后的JVM
堆
虚拟机栈
栈帧
操作数
本地变量表
动态链接
返回地址
本地方法栈
方法区
程序计数器
每一个线程私有计数器
GC作用域
常见的垃圾回收算法
引用计数
复制
标记清除
标记整理
题目1
1、JM垃圾回收的时候如何确定垃圾?是否知道什么是 GC Roots
什么是垃圾
简单的说就是内存中已经不再被使用到的空间就是垃圾
要进行垃圾回收,如何判断一个对象是否可以被回收
引用计数法
枚举根节点做可达性分析(根搜索路径)
case
Java 可以做GCRoots的对象
虚拟机栈(栈帧中的局部变量区,也叫做局部变量表
方法区中的类静态属性引用的对象。
方法区中常量引用的对象
本地方法栈中N( Native方法)引用的对象
2、你说你做过JVM调优和参数配置,请问如何盘点查看MM系统默认值
JVM的参数类型
标配参数
-verison
-help
java -showversion
X参数(了解)
-Xint
解释执行
-Xcomp
第一次使用就编译成本地代码
-Xmixed
混合模式
XX参数
Boolean类型
公式
-XX:+或者- 某个属性值
+表示开启
-表示关闭
Case
是否打印GC收集细节
-XX:+PrintGCDetails
-XX:-PrintGCDetails
是否使用串行垃圾收集器
-XX:-UseSerialGC
-XX:+UseSerialGC
KV设值类型
公式
-XX:属性key=属性值value
Case
-XX:MetaspaceSize=128m
-XX:MaxTenuringThreshold=15
jinfo举例,如何查看当前运行程序的配置
公式
jinfo -flag 配置项 进程编号
Case1
Case2
Case3
题外话(坑题)
两个经典参数:-Xms和-Xmx
这个你如何解释
-Xms
等价于 -XX:InitialHeapSize
-Xmx
等价于-XX:MaxHeapSize
查看JVM默认值
-XX:+PrintFlagsInitial
查看初始默认值
公式
java -XX:+PrintFlagsInitial -version
java -XX:+PrintFlagsInitial
Case
-XX:+PrintFlagsFinal
主要查看修改更新
公式
java -XX:+PirntFlagsFinal
java -XX:+PirntFlagsFinal -version
Case
PrintFlagsFinal举例,运行Java命令的同时打印出参数
Subtopic
-XX:+PrintCommandLineFlags
Subtopic
3、你平时工作用过的M常用基本配置参数有哪些?
基础知识复习
Case
常用参数
-Xms
初始大小内存,默认为物理内存1/64
等价于-XX:InitialHeapSize
-Xmx
最大分配内存,默认为物理内存1/4
等价于-XX:MaxHeapSize
-Xss
设置单个线程的大小,一般默认为512K~1024K
等价于-XX:ThreadStackSize
-Xmn
设置年轻代大小
-XX:MetaspaceSize
设置元空间大小
Subtopic
-Xms10m -Xmx10m -XX:MetaspaceSize=1024m -XX:+PrintFlagsFinal
典型设置案例
-XX:+PrintGCDetails
输出详细GC收集日志信息
GC
FullGC
-XX:SurvivoRatio
Subtopic
-XX:NewRatio
Subtopic
-XX:MaxTenuringThreshold
设置垃圾最大年龄
4、强引用、软引用、弱引用、虚引用分别是什么?
整体架构
强引用(默认支持模式)
Case
软引用
Case
弱引用
Case
软引用和弱应用的适用场景
你知道弱引用的话,能谈谈WeakHashMap吗?
虚引用
引用队列
Case
Case
GCRoots和四大引用的小总结
5、请谈谈你对ooM的认识
Java.lang.StackOverflowError
Java.lang.OutOfMemoryError:Java heap space
Java.lang.OutOfMemeoryError:GC overhead limit exceeded
Java.lang.OutOfMemeoryError:Direct buffer memory
Java.lang.OutOfMemeoryError:unable to create new native thread
非root用户登录Linux系统测试
服务器级别参数调优
Java.lang.OutOfMemeoryError:Metaspace
使用Java -XX:+PrintFlagsInitial命令查看本机的初始化参数,-XX:MetaspaceSize为21810376B(约20M)
6、G垃圾回收算法和垃圾收集器的关系?分别是什么请你谈谈
GC算法(引用计数/复制/标清/标整)是内存回收的方法论,垃圾收集器就是算法落地实现
因为目前为止还没有完美的收集器出现,更加没有万能的收集器,只是针对具体应用最合适的收集器,进行分代收集
4种主要垃圾收集器
串行垃圾回收器(Serial)
它为单线程环境设计并且只使用一个线程进行垃圾回收,会暂停所有的用户线程。所以不适合服务器环境
并行垃圾回收器(Parallel)
多个垃圾回收线程并行工作,此时用户线程是暂停的,适用于科学计算/大数据处理等弱交互场景
并发垃圾回收器(CMS)
用户线程和垃圾收集线程同时执行(不一定是并行,可能交替执行),不需要停顿用户线程
互联网公司多用它,适用于对响应时间有要求的场景
G1垃圾回收器
G1垃圾回收器将堆内存分割成不同的区域然后并发的对其进行垃圾回收
7、怎么查看服务器默认的垃圾收集器是那个?
生产上如何配置垃圾收集器的?
谈谈你对垃圾收集器的理解?
怎么查看默认的垃圾收集器是哪个?
默认的垃圾收集器有哪些
垃圾收集器
部分参数预先说明
DefNew
Default New Generation
Tenured
Old
ParNew
Parallel New Generation
PSYoungGen
Parallel Scavenge
ParOldGen
Parallel Old Generation
Server/Client模式分别是什么意思
新生代
串行GC(Serial)/(Serial Coping)
并行GC(ParNew)
并行回收GC(Parallel)/(Parallel Scavenge)
老年代
串行回收GC(Serial Old)/(Serial MSC)
并行GC(Parallel Old)/(Parallel MSC)
并发标记清除GC(CMS)
4步过程
初始标记(CMS initial mark)
并发标记(CMS concurrent mark)和用户线程一起
重新标记(CMS remark)
并发清除(CMS concurrent sweep)和用户线程一起
优缺点
优
并发收集低停顿
缺
并发执行,对CPU资源压力大
采用的标记清除算法会导致大量碎片
垃圾收集器配置代码总结
底层代码
实际代码
如何选择垃圾收集器
8、G1垃圾收集器
以前收集器特点
年轻代和老年代是各自独立且连续的内存块
年轻代收集使用单eden+S0 +S进行复制算法
老年代收集必须扫描整个老年代区域
都是以尽可能少而快速地执行GC为设计原则
G1是什么
特点
底层原理
Region区域化垃圾收集器
最大好处是化整为零,避免全内存扫描,只需要按照区域来进行扫描即可
回收步骤
4步过程
case案例
常用配置参数(了解)
-XX:+UseG1GC
-XX:G1HeapRegionSize=n : 设置G1区域的大小。值是2的幂,范围是1M到32M。目标是根据最小的Java堆大小划分出约2048个区域
-XX:MaxGCPauseMillis=n : 最大停顿时间,这是个软目标,JVM将尽可能(但不保证)停顿时间小于这个时间
-XX:InitiatingHeapOccupancyPercent=n 堆占用了多少的时候就触发GC,默认是45
-XX:ConcGCThreads=n 并发GC使用的线程数
-XX:G1ReservePercent=n 设置作为空闲空间的预留内存百分比,以降低目标空间溢出的风险,默认值是10%
和CMS相比的优势
小总结
9、生产环境服务器变慢,诊断思路和性能评估谈谈?
整机:top
uptime,系统性能命令的精简版
CPU:vmstat
查看CPU(包含不限于)
查看额外
查看所有CPU核信息
mpstat -P ALL 2
每个进程使用cpu的用量分解信息
pidstat -u 1 -p 进程编号
内存:free
应用程序可用内存数
查看额外
pidstat -p 进程号 -r 采样间隔秒数
硬盘:df
查看磁盘剩余空闲数
磁盘IO:iostat
磁盘I/O性能评估
查看额外
pidstat -d 采样间隔秒数 -p 进程号
网络IO:ifstat
默认本地没有,下载ifstat
查看网络IO
10、假如生产环境出现CPU占用过高,请谈谈你的分析思路和定位
结合Linux和JDK命令一块分析
案例步骤
1. 先用top命令找出CPU占比最高的
2. ps -ef或者jps进一步定位,得知是一个怎么样的一个后台程序
3. 定位到具体线程或者代码
ps -mp 进程 -o THREAD,tid,time
参数解释
-m 显示所有线程
-p pid进程使用cpu的时间
-o 该参数后是用户自定义格式
4. 将需要的线程ID转换为16进制格式(英文小写格式)
printf "%x\n" 有问题的线程ID
5. jstack 进程ID | grep tid(16进制线程ID小写英文) -A60
11、对于JDK自带的JVM监控和性能分析工具用过哪些?一般你是怎么用的?
是什么
性能监控工具
jps(虚拟机进程状况工具)
jinfo(Java配置信息工具)
jmap(内存映像工具)
jstat(统计信息监控工具)
题目2
其他
5.消息中间件
0 条评论
下一页