1、能详细说说 Java 类从被加载到可用,经历了哪几个阶段吗?每个阶段主要做什么?
java代码首先是存在于磁盘中,通过javac命令编辑成字节码文件。然后类加载器将这些字节码二进制数据加载进java虚拟机内存的方法区,并在堆中创建一个class对象。
具体过程是加载连接初始化。加载就是通过类的全限定名查找类的字节码文件...(根加载器,扩展加载器,应用/系统加载器,双亲委派,自定义加载器...)
连接包括:验证,准备,解析。验证是否有问题。准备,对于类的静态变量先进行分配空间,附默认值。解析,对于符号引用转化为直接引用。
初始化:对于静态变量静态代码块赋值初始化等
2、JVM 怎么判断一个对象是垃圾对象?
换言之,gc的原理。利用可达性分析,从gc root出发,对于不可达的对象认为是垃圾。root有虚拟机栈中引用的对象(局部变量),本地方法栈引用的对象(native),方法区静态变量引用的对象,方法区常量引用的对象。
gc的方法:标记-清除,就是对于垃圾直接清楚,易产生内存碎片。标记-复制,对于存活对象复制到新内存中,之前一块全部清理。需要一倍内存空间,见:新生代的servivor1和2。标记整理:清理后整理。不适合高频率。
垃圾回收器:单线程:serial 和serial old 会产生stw stop the world。
多线程:parallel scavenge ...
过渡:CMS ...
老年代的回收算法,只有cms是标记清除,其他两个是标记整理。

CMS阶段:1、初次标记,从gc root标记直达的 会stw 2、并发标记,从初始标记的对象继续遍历引用链标记 3、重新标记,对于并发标记期间,对象引用关系发生变化的重新操作。会stw 4、标记清除。
G1:(和cms类似,是cms后继者 是将堆划分多个大小相等的区域,每个区域都可以是新生代的伊甸区,servivor区,老年区等,还有个巨大..。可预测停顿时间等等)
阶段:1、初次标记,同理gc root 直达对象,还有划分的region(root region) 会stw
2、并发标记 3、最终标记,同cms的重新标记 。会stw 4、筛选回收,对于存活对象复制到新的region。会stw
点:rset,satb
3、 进程状态以及状态之间的转换
新建--就绪--运行--阻塞--结束
新建-就绪:进程创建完成,等待cpu调度。
就绪-运行:cpu轮转到该进程,开始执行
运行-就绪:时间片用完,回到就绪队列
运行-阻塞:等待IO资源,等待信号量
阻塞-运行:资源就绪
阻塞-结束:运行完成结束,程序异常终止
4、Java 线程池的作用
节约资源:避免频繁创建线程,浪费资源。
提高效率:任务来了直接响应
便于管理:统一控制线程数量
5、线程池处理任务的流程
1、当一个新任务来了,如果且任务数少于核心线程数,(核心线程池没满),创建一个新的核心线程执行
2、如果核心线程数满了,就进入任务队列。
3、如果任务队列都满了,判断是否达到最大线程数,如果没有,就创建非核心线程执行任务
4、如果达到了,就进行拒绝策略,如直接抛弃任务。
6、synchronized 跟 ReentrantLock 有什么区别?
(Synchronized本质是两条字节码指令monitertenter和moniterexit指令,再内部内嵌了一个计数器实现的)
-
synchnorized是关键字,ReentrantLock是类。
-
synchnorized是自动释放锁,后者需要手动释放,否则容易引起死锁。
-
前者 可重入,不可中断,非公平, 后者 可重入,可中断,可以设置公平还是不公平。(可重入锁:对象获取锁后还可以再次获取该锁)
-
前者无法判断锁的状态,后者可以知道是否获取到锁。
-
前者 线程1获得锁,线程2等待... 后者 线程1获得锁,线程2 tryLock,如果没获取到就放弃
-
前者 适合少量 后者适合大量锁同步问题
7、死锁
8、AQS 的实现原理
9、生产者消费者问题
一个任务往里加,当不为空时候,wait等待。为空执行完之后唤醒其他线程。注意这里判断条件要while,否则会有虚假唤醒。(详细见狂神视频)理解是:比如两个线程都可以加。不为空,两个都等待wait,为空,一个开始加1然后唤醒notify其他线程,另一个就没有判断是否为空,直接继续加1了。
用condition的升级版,想要做到让线程按顺序执行,或者说精准唤醒。就是condition1.await()等待condition2.signal()精准唤醒监视器2。
10、锁的是什么?callable
synchronized锁的对象是方法的调用者。如果方法上有static,变成静态方法,那锁的就是class类对象了。
面试官:如何开启多线程?Thread,Runnable接口,线程池。这个你要不熟悉建议别说/和runable区别:有返回值,可以抛异常。方法不同,run'call
11、对于高并发
