当使用 ThreadLocal 维护变量时,其为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立的改变自己的副本,而不会影响其他线程对应的副本。
ThreadLocal 内部实现机制:
每个线程内部都会维护一个类似 HashMap 的对象,称为 ThreadLocalMap,里边会包含若干了 Entry(K-V 键值对),相应的线程被称为这些 Entry 的属主线程;
Entry 的 Key 是一个 ThreadLocal 实例,Value 是一个线程特有对象。Entry 的作用即是:为其属主线程建立起一个 ThreadLocal 实例与一个线程特有对象之间的对应关系;
Entry 对 Key 的引用是弱引用;Entry 对 Value 的引用是强引用。
09. Atomic 关键字:
答:可以使基本数据类型以原子的方式实现自增自减等操作。
10. 线程池有了解吗?(必考)
答:
java.util.concurrent.ThreadPoolExecutor 类就是一个线程池。客户端调用 ThreadPoolExecutor.submit(Runnable task) 提交任务,线程池内部维护的工作者线程的数量就是该线程池的线程池大小,有 3 种形态:
当前线程池大小 :表示线程池中实际工作者线程的数量;
最大线程池大小 (maxinumPoolSize):表示线程池中允许存在的工作者线程的数量上限;
核心线程大小 (corePoolSize ):表示一个不大于最大线程池大小的工作者线程数量上限。
如果运行的线程少于 corePoolSize,则 Executor 始终首选添加新的线程,而不进行排队;
如果运行的线程等于或者多于 corePoolSize,则 Executor 始终首选将请求加入队列,而不是添加新线程;
如果无法将请求加入队列,即队列已经满了,则创建新的线程,除非创建此线程超出 maxinumPoolSize, 在这种情况下,任务将被拒绝。
限于篇幅有限,更多高并发编程中的问题,请参考:
1. Java 多线程编程核心技术
2. Java多线程与并发编程
小结:本小节内容涉及到 Java 中多线程编程,线程安全等知识,是面试中的重点和难点。
JVM 内存管理
既然是 Java 开发面试,那么对 JVM 的考察当然也是必须的,面试官一般会问你对 JVM 有了解吗?
我通常都会把我所了解的都说一遍,包括:JVM 内存划分、JVM 垃圾回收的含义,有哪些 GC 算法,年轻代和老年代各自的特点统统阐述一遍。
【JVM 垃圾回收机制】
01. JVM 内存划分:
方法区(线程共享):常量、静态变量、JIT(即时编译器) 编译后的代码也都在方法区;
堆内存(线程共享):垃圾回收的主要场所;
程序计数器: 当前线程执行的字节码的位置指示器;
虚拟机栈(栈内存):保存局部变量、基本数据类型变量以及堆内存中某个对象的引用变量;
本地方法栈 :为 JVM 提供使用 native 方法的服务。
02. 类似-Xms、-Xmn 这些参数的含义:
答:
堆内存分配:
JVM 初始分配的内存由-Xms 指定,默认是物理内存的 1/64;
JVM 最大分配的内存由-Xmx 指定,默认是物理内存的 1/4;
默认空余堆内存小于 40% 时,JVM 就会增大堆直到-Xmx 的最大限制;空余堆内存大于 70% 时,JVM 会减少堆直到 -Xms 的最小限制;
因此服务器一般设置-Xms、-Xmx 相等以避免在每次 GC 后调整堆的大小。对象的堆内存由称为垃圾回收器的自动内存管理系统回收。
非堆内存分配:
JVM 使用-XX:PermSize 设置非堆内存初始值,默认是物理内存的 1/64;
由 XX:MaxPermSize 设置最大非堆内存的大小,默认是物理内存的 1/4;
-Xmn2G:设置年轻代大小为 2G;
-XX:SurvivorRatio,设置年轻代中 Eden 区与 Survivor 区的比值。
03. 垃圾回收算法有哪些?
答: