目录
一、并发、并行、串行的区别
二、并发的三个特性
三、并发编程三要素
四、死锁如何避免
原因:
1、一个锁资源只能被一个线程所占用。
2、一个线程阻塞等待另一个资源,不释放已占用的锁资源。
3、一个线程已经获得的锁资源,在未下使用完之前不可被强行剥夺。
4、若干个线程形成头尾相接的循环等待资源关系。
解决办法:
1、按照相同顺序加锁。
2、一次性去获取想要的锁资源。
3、注意设置锁时限。
4、注意死锁的监控和预防,确保第一时间发现死锁。
五、volatile关键字是如何保证可见性、有序性
1、对于加了volatile关键字的成员变量,在对这个变量进行修改时,会直接将CPU高级缓存中的数据写回到主内存中,对这个变量的读取也会直接从主内存中读取,从而保证可见性;
2、在对volatile修饰的成员变量进行读写时,会插入内存屏障,而内存屏障可以达到禁止重排序的效果,从而可以保证有序性。
六、线程池的底层工作原理
1、当核心线程数小于corePoolSize,无论是否有空闲的线程,都会创建新线程来处理新添加的任务。
2、当线程大于等于corePoolSize,缓存队列workQueue未满,新的任务会添加到缓存队列中。
3、当缓存队列workQueue满了,线程数小于maxinumPoolSize,会创建新线程来处理新的线程。
4、当缓存队列workQueue满了,线程数等于maxinumPoolSize,会采用对应的拒绝策略进行处理。
5、当线程池中的线程大于corePoolSize,线程空闲时间超过keepAliveTime,线程将会被终止。
七、java类加载
双亲委派机制
1、向上委派查找,向下委派加载。
AppClassLoader(系统类加载器,线程上下文加载器,是自定义加载器的父类) -> ExtClassLoader -> Bootstrap classloader 从缓存开始查找类相关信息,然后再从sun.boot.class.path(%JAVA_HOME%/lib 下rt.jar和class文件) 下加载全限类名,lib.dir.ext(%JAVA_HOME%/lib/ext)下,class.path。
继承classloader 实现类加载器
2、类加载过程
1、加载:将java文件加载成二进制的class文件,并检验是否符合jvm数据结构。
2、连接(resolve):a、验证:检查是否符合jvm规范。
b、准备:将类和接口的静态变量,赋予初始值。
c、解析:将符号引用转为直接引用,直接指向引用地址的指针。
3、初始化: 静态代码块和构造器等相关信息。
八、java类加载器有哪些
AppClassLoader: 系统类加载器,线程上下文类加载器,自定义加载器的父类。
ExtClassLoader: 扩展类加载器,加载%JAVA_HOME%/lib/ext目录下jar和class文件。
Bootstrap ClassLoader: 启类加载器,加载%JAVA_HOME%/lib下jar和class文件。
九、JVM内存模型
运行时数据区:
线程私有:
栈桢: JVM stack: 虚拟机栈,native stack : 本地方法栈。
程序计数器:指线程执行到哪个步骤的指针。
堆:
新生代(1/3):Eden(8/10),Survivor to (1/10),Survivor(1/10)
老年代(old Gem)(2/3):动态年龄(4位,最大值是15)
方法区(元数据空间metaspace): 类相关信息和常量,方法区是在堆内连接空间,元数据空间转移到堆外的。
扩展话题: directbuffer 直接堆内存(jdk1.4 nio)
十、JVM有哪些垃圾回收器?他们都是怎么工作的?什么是STW?
1、垃圾回收器:
分代:
serial (年轻代)/ seral old (老年代): 单线程回收垃圾回收器,适用于单核cpu和几十M内存。
perellel scavenge(ps) / perellel old (po): 在serial 的基础上进行多线程回收器,jdk1.8 默认的垃圾回收器组合。
perellel new : 是为配合cms ,在perellel secavoge 基础上做的改进。
CMS (concurrent mark sweept):有四个阶段:
a、 初始标记:扫描GC Roots直接引用的对象,stw。
b、 并发标记: 继续标记其它对象,与应用程序是并发进行的。
i: 预清理标记:
ii: 预清理可中断标记:提前解决young gc可中断
c、重新标记: 对并发执行阶段的对象进行重新标记。
d、并发清除: 在清除的过程中,会产生留下新的垃圾,这就叫浮动垃圾;
分区: G1(garbage first)垃圾优先 ,jdk1.8 可以使用的 ,物理上不分区,但逻辑上是分代,分为多个region 区,最多2048个(默认),年轻代只占堆的百分之五。
a、初始化标记: 扫描GC root 直接引用的对象。
b、标记Region:通过Rset标记上一个阶段标记的Region引用到Old区Region。
c、并发标记: 继续标记其它对象,只需要标记第二阶段标记的Region。
d、重新标记:跟cms差不多,扫描一个old region,不会扫描整个old区。
e、清除:采用的复制算法,处理垃圾最多的old 。
zgc (jdk 11)、epsilon (只管分配,不负责回收)、shennadoah (是openjdk 的一种算法)
2、STW: stop - the -world ,在执行垃圾回收过程,jvm 处于一种冻结的状态,所有线程都会停止,gc 线程除外。