Java面试八股文
面试准备,java八股文学习。
Java面试八股文
1. Java中线程的实现方式
可以有三种,四种,五种。追其底层,只有一种,基于Runnable。
1.1 继承Thread类,重写run方法
Thread类实现了runnable
1.2 实现Runnable接口,重写run方法
其中有lambda表达式实现,称为第五种
1.3 实现Callable,重写call方法,配合FutureTask
想拿到返回结果,Thread和Runnable不能实现,此方法可以拿到返回结果。
FutureTask实现了RunnableFuture接口,RunnableFuture继承了Runnable和Future两个接口。
1.4 基于线程池构建线程
ThreadPoolExecutor,每次构建的线程是Worker,Worker实现了Runnable
2. Java中线程的状态
五种、六种、七种。
2.1 五种,传统的线程状态,操作系统层面

2.2 六种,Java给线程准备的(优先回答)

2.3 七种,将六种状态划分中的运行和就绪态拆开
3. Java中如何停止线程
3.1 stop,强制结束,(不用)
3.2 使用共享变量,(很少会用)
手动添加全局共享变量flag
,线程内部通过while(flag)
控制,通过修改flag
破坏死循环。
3.3 interrupt方式
线程内部的中断标记位interrupt
,通过isInterrupted()
来查询线程的中断标记位状态,interrupt()
来中断线程(置true
),interrupted
获取中断标记位再归位(false
)。
如果线程正在休眠,修改了interrupt
位,会抛出异常,让run
方法结束。也就是在线程的WAITING
和TIMED_WATING
状态即可停止线程。
4. Java中sleep和wait方法的区别
4.1 sleep是Thread类中的static方法,wait是Object类方法
4.2 sleep是TIMED_WAITING,休眠结束自动被唤醒,wait输入WAITING,需手动唤醒
4.3 有锁时sleep不会释放锁,wait会
4.4 sleep有锁没锁都可执行,wait只有在有锁才能执行
wait方法会将持有锁的线程从owner进去WaitSet集合,修改ObjectMonitor对象(ObjectMonitor负责维护锁的状态,实现底层的锁机制),不持有synchronized锁,无法操作。
5. 并发编程的三大特性
5.1 原子性
5.2 可见性
5.3 有序性
内容太多,记不完:https://www.bilibili.com/video/BV1Av4y187hf?p=6
6. 什么是CAS,有什么优缺点
Compare And Swap。
比较和交换,CPU并发原语,替换内存某个位置值时,先查看内存值是否与预期一致,一致则替换,返回true。不一致返回false。
优点:不必让线程进入阻塞状态,不必挂起,避免用户态和内核态切换。
缺点:
- 不停地while循环执行CAS,消耗CPU(解决:指定最大循环上限,超出则失败/挂起线程)。
- 只能保证对一个变量的操作是原子性的,无法实现多行代码原子性,存在ABA问题(解决:为变量增加版本信息)。
- 并发量大时竞争多,成功率低,性能下降。(解决:LongAdder,将累加操作分摊到多个变量(cell)中,线程选择一个累加,需要获取累加结果时求cell总和)
7. @Contended注解有什么用
解决伪共享问题(解决缓存行同步带来的性能问题)
CPU缓存L1时默认以缓存行为单位来存储,一般为64字节,缓存行中有数据改变则缓存行无效,需重新加载整个缓存行,影响CPU性能。
@Contended注解将当前类属性独占缓存行(剩余空间填无意义数据),避免缓存行失效造成的性能问题。
需要被频繁修改的变量添加@Contended注解独占缓存行,不会影响其他变量。
8. Java中的四种引用类型
强、软、弱、虚
8.1 强引用:把一个对象赋给引用变量
1 | User user = new User(); |
最常见,始终处于可达状态,不会被垃圾回收机制回收(在函数内定义,弹栈后会被回收),造成Java内存泄露的主要原因之一。
8.2 软引用:SoftReference
系统内存足够不会被回收,内存空间不足会被回收。软引用用在内存敏感程序作为缓存使用。
8.3 弱引用
只有弱引用的对象,只要垃圾回收机制一进行,不管内存够不够,总会回收该对象的内存。解决内存泄露问题。
8.4 虚引用
不能单独使用。主要作用是跟踪对象被垃圾回收的状态。
通常与ReferenceQueue(引用队列)一起使用。当虚引用关联的对象被垃圾回收器回收时,虚引用会被放入与之关联的引用队列中。通过检查引用队列中的虚引用,可以得知对象已经被回收了。