- 最大的挑战是什么,成就感的事情,项目是干嘛的,用了哪些三方件,怎么实现的。
- JVM的垃圾回收算法有哪些。怎么判断哪些对象是否需要回收。GC root一般如何选择。JDK1.8的垃圾回收器有哪些,使用的什么垃圾回收器。对于老年代中有新生代的引用,如何回收这部分,是否需要对老年代进行全面扫面。
垃圾收集器:G1垃圾收集器 + CMS垃圾收集器
可达性分析算法:
GC Roots的根对象作为起始节点集,引用关系向下搜索如果某个对象到GC Roots间没有任何引用链相连,则从GC Roots到这个对象不可达时,则证明此对象是不可能再被使用的。
固定可作为GC Roots的对象:
• 在虚拟机栈(栈帧中的本地变量表)中引用的对象,譬如各个线程被调用的方法堆栈中使用到的参数、局部变量、临时变量等。
• 在方法区中类静态属性引用的对象,譬如Java类的引用类型静态变量。
• 在方法区中常量引用的对象,譬如字符串常量池(String Table)里的引用。
• 在本地方法栈中JNI(即通常所说的Native方法)引用的对象。
• Java虚拟机内部的引用,如基本数据类型对应的Class对象,一些常驻的异常对象(比如NullPointExcepiton、OutOfMemoryError)等,还有系统类加载器。
• 所有被同步锁(synchronized关键字)持有的对象。
• 反映Java虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等。
分代收集理论:
- 弱分代假说:朝生夕灭。
- 强分代假说:熬过多次垃圾收集过程的对象越难以消亡。
标记-清除算法:
标记-复制算法:新生代(1个eden+2个survivor)
标记-整理算法:老年代
新生代对象有可能被老年代引用:跨代引用假说
只需在新生代上建立一个全局的数据结构(称为“记忆集”,RememberedSet),这个结构把老年代划分成若干小块,标识出老年代的哪一块内存会存在跨代引用。此后当发生Minor GC时,只有包含了跨代引用的小块内存里的对象才会被加入到GC Roots进行扫描。虽然这种方法需要在对象改变引用关系(如将自己或者某个属性赋值)时维护记录数据的正确性,会增加一些运行时的开销,但比起收集时扫描整个老年代来说仍然是划算的。
多线程
ThreadPoolExecutor:
线程池主要有如下6个参数:
1. corePoolSize(核心工作线程数)
2. maximumPoolSize(最大线程数)
3. keepAliveTime(多余线程存活时间)
4. workQueue(队列)
5. threadFactory(线程创建工厂)
6. handler(拒绝策略):当线程池和队列都满了,再加入线程会执行此策略
线程池工作流程:
1. 判断核心线程池是否已满,没满则创建一个新的工作线程来执行任务。
2. 判断任务队列是否已满,没满则将新提交的任务添加在工作队列。
3. 判断整个线程池是否已满,没满则创建一个新的工作线程来执行任务,已满则执行饱和(拒绝)策略
层序遍历算法(右视图,二叉树从右边看看到的节点信息)
public List get(TreeNode treeNode) {
if (treeNode == null) {
return new ArrayList();
}
List result = new ArrayList<>();
Deque<TreeNode> deque = new LinkedList();
deque.offer(treeNode);
while (!deque.isEmpty()) {
int size = deque.size();
List list = new ArrayList();
for (int i = 0; i < size; i++) {
TreeNode node = deque.poll();
list.add(node.val);
if (node.left != null) {
deque.offer(node.left);
}
if (node.right != null) {
deque.offer(node.right);
}
}
int listSize = list.size();
if (listSize > 0) {
result.add(list.get(listSize - 1));
}
}
return result;
}