疏漏总结(一)

最近在靠面小公司面试官,查缺补漏,面了一个叫xxx的公司,和面试官聊了两个小时,总结一下不会的知识点。

1.怎么判断一个对象要被回收了
有两种方法可以判断,一种是引用计数(js),一种是可达性分析(jvm)。
当从GC ROOTS开始,一个方法没有在任何一个引用链上出现,就是要被回收了。
可以作为GC Roots的 :
①Java虚拟机栈中引用的对象,虚拟机栈中(栈帧)
②静态属性引用的对象,static对象
③常量引用的对象,final对象
④本地方法栈中引用的对象,nio

2.什么是幸存者区

Survivor Space幸存者区,用于保存在eden space内存区域中经过垃圾回收后没有被回收的对象。Survivor有两个,分别为To Survivor、 From Survivor,这个两个区域的空间大小是一样的。执行垃圾回收的时候Eden区域不能被回收的对象被放入到空的survivor(也就是To Survivor,同时Eden区域的内存会在垃圾回收的过程中全部释放),另一个survivor(即From Survivor)里不能被回收的对象也会被放入这个survivor(即To Survivor),然后To Survivor 和 From Survivor的标记会互换,始终保证一个survivor是空的。

疏漏总结(一)

3.如果避免缓存击穿

可以将这个不存在的数据直接写入缓存,但是过期时间设置短一点。
或者使用布隆过滤器,将所有有可能访问的数据都放进位图里面。

4.ThreadLocal原理
首先 ThreadLocal 是一个泛型类,保证可以接受任何类型的对象。

因为一个线程内可以存在多个 ThreadLocal 对象,所以其实是 ThreadLocal 内部维护了一个 Map ,这个 Map 不是直接使用的 HashMap ,而是 ThreadLocal 实现的一个叫做 ThreadLocalMap 的静态内部类。最终的变量是放在了当前线程的 ThreadLocalMap 中,并不是存在 ThreadLocal 上,ThreadLocal 可以理解为只是ThreadLocalMap的封装,传递了变量值。

实际上 ThreadLocalMap 中使用的 key 为 ThreadLocal 的弱引用,弱引用的特点是,如果这个对象只存在弱引用,那么在下一次垃圾回收的时候必然会被清理掉。

所以如果 ThreadLocal 没有被外部强引用的情况下,在垃圾回收的时候会被清理掉的,这样一来 ThreadLocalMap中使用这个 ThreadLocal 的 key 也会被清理掉。但是,value 是强引用,不会被清理,这样一来就会出现 key 为 null 的 value。

ThreadLocalMap实现中已经考虑了这种情况,在调用 set()、get()、remove() 方法的时候,会清理掉 key 为 null 的记录。如果说会出现内存泄漏,那只有在出现了 key 为 null 的记录后,没有手动调用 remove() 方法,并且之后也不再调用 get()、set()、remove() 方法的情况下。

5.堆的分区
Eden,Suriviver,Old Generation
Eden和Surviver都属于新生代,Old Generation属于老年代。

6.线程池submit的原理

线程的执行有两种方式,一种是submit(runnable v)的形式,一种是execute(runnable b) 的形式。

不同的是submit可以返回一个future的实现类,相同的一点是submit底层其实也是调用的execute。

调用execut方法,首先判断传入的参数是否为空,如果为空,抛出异常,如果不为空,使用获取ctl值,计算出当前线程状态码,通过状态码计算出当前线程池工作线程是否小于核心线程数量。

如果小于,判断添加工作线程操作是否正常,如果正常,直接返回,如果不正常,继续执行获取ctl值,在添加工作线程的过程中,首先通过循环的方式保证ctl在加1的情况下状态同步,如果不同步,一直循环到同步为止。

添加完成后,创建线程工作对象,把工作线程添加到set集合中,并执行.start,如果执行不成功,从set中删除添加的worker对象,并且ctl回滚到之前没有自增的值。