Java
1.ThreadLocal
ThreadLocal实现线程本地存储的功能,同一个ThreadLocal所包含的对象,在不同的Thread中有不同的实例,获取ThreadLocal对象时其实是在Thread类中的Map类型的threadLocals变量中通过ThreadLocal变量为键值进行获取。
2.volatile的作用和原理
被volatile修饰的变量保证Java内存模型中的可见性和有序性。
可见性:当一个线程修改了一个被volatile修饰的变量的值,新值会立即被刷新到主内存中,其他线程可以立即得知新值。
有序性:禁止进行指令重排序。
volaitle底层是通过内存屏障来实现可见性和有序性。内存屏障是一个CPU的指令,他的作用有两个,一是保证特定操作的执行顺序,二是保证某些变量的内存可见性。内存屏障告诉编译器和CPU,不管什么指令都不能和这条内存屏障指令重排序,另一个作用是强制刷出各种CPU的缓存资源,因此任何CPU上的线程都能读取到这些数据的最新版本。
3.J.U.C中的锁
Java提供了两种锁机制来控制多个线程对共享资源的互斥访问。
实现
公平锁
等待可中断
条件
性能
synchronized
JVM
非公平
不可中断
/
大致
ReentrantLock
JDK
非公平/公平
可中断
可绑定多个Condition
相同
除非要使用ReentrantLock的高级功能,否则优先使用synchronized,synchronized是JVM实现的一种锁机制,JVM原生的支持它,而ReentrantLock不是所有的JDK版本都支持。synchronized锁释放由JVM保证,ReentrantLock需要显式的释放。
4.atomic包里的一些问题
atomic是使用volatile和CAS来实现的
5.HashMap的扩容
当HashMap的容量到达threshold时,需要进行动态扩容,将容量扩大为原来的两倍,然后将存储的数据进行rehash。
6.Semaphore信号量用来做什么?
Semaphore信号量类似于操作系统的信号量,可以控制对互斥资源的访问线程数。
7.Java内存模型
CPU和内存之间增加高速缓存。
所有的变量都存储在主内存中,每个线程有自己的工作内存,工作内存存储在高速缓存中,保存了该线程使用变量的拷贝。
线程只能直接操作工作内存中的变量,不同线程之间的变量值传递需要通过主内存来完成。
内存模型的三大特性:
原子性:Java内存模型保证了read、load、use、assign、store、write、lock、unlock操作具有原子性
实现:原子类、synchronized
可见性:当一个线程修改了共享变量的值,其他线程能够立即得知这个修改。
Java内存模型是通过在变量修改后将新值同步回主内存,在变量读取前从主内存刷新变量值来实现可见性
实现:volatile、synchronize、final
有序性:在本线程内观察,所有操作都是有序的。在一个线程观察另一个线程,所有操作都是无序的,无序是因为发生了指令重排序。
实现:volatile、synchronized
8.Java内存空间是怎么分配的?
对象优先在Eden区分配
大对象直接进入老年代
长期存活的对象进入老年代
动态对象年龄判定
空间分配担保
8.Full GC触发条件
System.gc()
老年代空间不足
空间分配担保失败
8.类加载机制
加载:1.通过类文件加载二进制字节流 2.在方法区创建类的动态存储结构 3.在内存中创建class对象作为方法去的访问入口。
验证:验证class文件的字节流是否符合虚拟机要求。
准备:为类变量分配内存并设置初始值。
解析:将常量池的符号引用替换为直接引用的过程。
初始化:执行Java程序代码。
8.新生代和老年代可以转换吗?
对象优先分配在新生代的Eden区,通过长期存活(达到一定岁数)的对象进入老年代和动态对象年龄判定使对象从新生代进入老年代。
9.这些内存里面的垃圾怎么回收?
引用计数法和可达性分析法。回收算法包括:标记-清除、标记-整理、复制、分代收集算法。
10.怎么判断是垃圾?GCRoot可以为哪些?
可达性分析法中,从GC Root出发,不可达的是可以被回收的对象。
Java虚拟机栈局部变量表中引用对象。
本地方法栈JNI中引用的对象。
方法区中类静态变量引用的对象。
方法去中常量引用的对象。
11.G1收集器
垃圾收集器都存在 Stop The World 的问题,G1对这个问题进行了优化,G1对整个新生代和老年代一起回收,把堆划分为多个大小相等的独立区域region,使得每个region可以单独进行垃圾回收,通过记录每个region垃圾回收时间以及回收所获得的空间(通过过去回收的经验获得),并维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的region。
初始标记 -> 并发标记 -> 最终标记 -> 筛选回收
特点:
空间整合:基于标记-整理和复制,不会产生内存空间碎片
可预测的停顿:也可以并发执行
8.BIO、NIO、AIO
BIO,同步阻塞IO,一个线程处理一个连接,发起和处理IO请求都是同步的
NIO,同步非阻塞IO,一个线程处理多个链接,发起IO请求是非阻塞的,处理IO请求是同步的(轮询)
AIO,异步非阻塞IO,一个有效请求一个线程,发起和处理IO请求都是异步的。
9.AQS
描述
FutureTask
用来封装Callable的返回值
BlockingQueue
当队列中没有元素时take()被阻塞,当队列满时put()被阻塞
ForkJoin
大的计算任务拆分成小任务,并行计算
10.JUC
描述 CountDownLatch countDown()会使计数器减1,当计数器为0时,调用await()的线程会被唤醒 CyclicBarrier await()会使计数器减1,当计数器为0时,所有调用await()的方法会被唤醒 Semaphore 类似于操作系统的信号量,可以控制对互斥资源的访问线程数
11.实现线程安全的方法
不可变
synchronized和ReentrantLock
CAS、AtomicInteger
TreadLocal
12.IO与NIO
I/O
NIO
数据打包和传输方式
流
块
是否阻塞
阻塞
非阻塞
13.NIO
通道(Channel):对原I/O包中的流的模拟,可以通过它读取和写入数据,流是单向的,通道是双向的,可以同时用于读、写或者同时用于读写。
缓冲区:不会直接对通道进行读写数据,而是要先经过缓冲区。
选择器(Selector):在Socket NIO用于IO复用。
14.Class.forName()怎么执行的?
15.守护线程是什么?守护线程是怎么退出的?
守护线程是在程序运行时提供后台服务的线程,不属于程序运行中不可或缺的部分。
当程序中所有非守护线程结束时,程序也就终止,同时杀死所有的守护线程。
16.Stack与ArrayList的区别
Stack是用Vector实现的,Queue是用ArrayList实现的,所以比较Stack与ArrayList的区别就是比较这两者之间的区别。
一个先进先出,一个后进先出
一个线程不安全,一个线程安全
17.HashMap的rehash过程
HashMap中使用一个技巧,和将哈希值与旧容量进行&运算,如果位上为0则在原位置,如果为1则在下边。
18.hashcode和equals的区别
equals用来判断实体在逻辑上是否相等,当重写equals方法时要重写hashcode方法。
如果两个对象通过equals判定相等,则hashcode相等。
hashcode相等,equals不一定相等。
19.equals和==的区别?我要比较内容呢?
equals:用来比较逻辑上是否相等
==:用来判断两个对象地址是否相同,即是否是同一个对象。
20.Java代码编译过程
词法分析 -> 语法分析 -> 语义分析 -> 字节码生成
21.如何设计hash函数
22.常用的线程池
23.分段锁
JVM
1.运行时数据区域
程序计数器
JVM栈
本地方法栈
堆
方法区
运行时常量池
功能
记录正在执行的虚拟机字节码指令的地址
栈帧用于存储局部变量表、操作数栈、常量池引用等信息
与JVM栈类似,为本地方法服务
对象分配区域,垃圾收集的主要区域
用于存访加载的类信息、常量、静态变量、即时编译器编译后的代码
方法区的一部分,存放生成的字面量和符号引用
线程私有
线程私有
线程私有
公有
公有
公有
垃圾收集
不需要
不需要
不需要
需要(垃圾回收的主要区域)
类的卸载:1.类实例被回收2.加载类的classloader被回收3.class对象没有被引用
方法区在jdk1.8以前放在永久代中,jdk1.8以后放在本地内存中,而不是JVM内存
需要
2.垃圾收集算法
新生代
老年代
垃圾收集算法
复制(Eden:Survivor)
标记-清除/标记-整理
GC
Minor GC
Full GC
触发条件
Eden空间满时
1.调用System.gc()
2.老年代空间不足
3.空间分配担保失败
3.类加载过程:
加载:从各种渠道获取二进制字节流转化为方法区的运行时存储结构,在内存中生成一个class对象作为访问入口。
验证:确保字节流符合当前虚拟机的要求
准备:为类变量分配内存并设置初始值
解析:将常量池的符号引用替换为直接引用的过程
初始化:虚拟机执行类构造器clinit方法的过程。()是由编译器自动收集类中所有类变量的赋值动作和静态语句块中的语句合并产生的
4.引用类型
描述
强引用
不会被回收
软引用
只有在内存不够的情况下才会被回收
弱引用
一定会被回收,只能存活到下一次垃圾回收发生之前
虚引用
不会对其生存时间造成影响,唯一目的是在这个对象被回收时收到一个系统通知
5.垃圾收集算法
描述
不足
标记-清除
标记要收集的对象,然后清除