面试官: 这些都不清楚,如何pass?

简介: 面试官: 这些都不清楚,如何pass?

背景

本文涉及的六个问题,全部出自于Java小面的小朋友在大厂面试,所遇到问题。

问题本身不难,都是些基础的概念,这些问题的价值在于每一个问题背后都可以挖出很多要点。

这些问题相当于是一个垫脚石,基本如果这些问题都回答不好,那么问深层次八股文的机会都不会有,面试必挂。

所以大家请耐心看完,已经会的就当是温故知新了,当然说的有错或者纰漏也欢迎评论指正。

一、并发基础干货,非常干

1-请你说一说什么是线程和进程?

  • 区别

进程:有独立内存空间,每个进程中的数据空间都是独立的。

线程:多线程之间堆空间与方法区是共享的,但每个线程的栈空间、程序计数器是独立的,线程消耗的资源比进程小的多。

  • 关系

进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡过程。

一个进程可以有一个或者多个线程组成;线程是进程中的一个执行单元,负责当前进程中任务的执行。

  • 线程的上下文切换是什么?

线程任务状态的保存及再加载的过程就叫做上下文切换。

  • 线程的并发与并行有啥区别?

并发(Concurrent):同一时间段内,多个任务都会被执行到 ,但不是在单位时间内同时执行。

并行(Parallel):单位时间内多个任务同时执行,并行上限取决于CPU核数。

2-使用多线程会带来什么问题?

  • 详细说说线程安全问题

线程安全问题出现在对同一块内存地址值的访问,如果这块内存地址值永远都不会改变,那么就不会出现线程安全问题。相反这个值,如果会被改变,那么多个线程就要考虑一个问题,大家由于上下文切换的缘故,在轮到其中一个线程访问该值的时候,是否读到的值和其他线程是同一个,线程安全问题由此产生。

  • 原子性、有序性和可见性深入地谈一下

➢ 原子性:指一组操作是一个完整的个体,要不都执行,要不不执行;

➢ 有序性:写程序是按照一定顺序,但程序在执行过程中由于指令重排,执行顺序会被调整;

➢ 可见性:仅在多线程有读写的情况需要考虑,一个线程修改内存中某一个值时,需要保证其他线程能读到修改的值,而不是原值。

3-什么是死锁?如何排查死锁?

  • 排查过程最好详细说明,最少说一种排查方案,越多越好

出现死锁,使用Arthas连接,对应JVM实例,thread -b命令一键式检测死锁。

当然这边还能提一嘴,JVM自带的jstack命令。

4-说一说JMM与happens-before?

这道题坑是比较大的,首先一点对于刚接触Java的程序员来说,可能还有一个JVM内存模型八股文被广泛传颂,但是注意一点你说了它,那就尬住,

  • 什么是 JMM 内存模型?

JMM定义是Java语言与操作系统内存是如何交互;而JVM内存模型,指的是JVM实例运行时内存区域是如何划分的。

其实这点你能明确讲到,其他的深入再说说,不同系统有不同的实现细节等等,这些就都是锦上添花了,能衍生自己擅长的那就是最好的。

  • 什么是 happens-before 规则?

涉及的规则不止我下面罗列的,但是以下四条是我认为比较关键的点,且大家的说法也基本都是如出一辙,这里我就拿相关资料上所描述的内容,

➢ 程序次序规则:在一个线程中,按照代码的顺序,前面的操作happens-before于后面的任意操作

➢ Volatile变量规则:对一个volatile修饰的变量的写, happens-before与任意后续对这个变量的读

➢ 传递性:如果A happens-before B,并且B happens-before C,则A happens-before C

➢ 锁定规则:对一个锁的解锁, happens-before与随后对这个锁的加锁

如果能能再展开讲讲线程启动规则、线程终结规则、线程中断规则、对象终结原则,那很不错。

5-为什么使用线程池?如何创建线程池?

  • 手动创建和自动创建线程池都需要介绍

手动创建,使用ThreadPoolExecutor的构造函数,配置线程池参数。

自动创建,使用Executors提供的几个类方法直接创建。

  • 最好能介绍一下线程池的实现原理

由于频繁创建线程是会有额外的时间开销的,因此池化的理念同样被JDK中线程池引入并实现。

这里重点关注两个参数需要拿出来讲讲,corePoolSize、maxPoolSize,参数的关系如下所述,

➢线程数 < corePoolSize,就算有工作线程处于空闲状态,仍旧会创建新线程执行task。

➢线程数 >= corePoolSize,但 < maxPoolSize,将任务放入task队列中。

➢队列已满,并且线程数 < maxPoolSize,那么创建新线程来执行task。

➢队列已满,并且线程数 >= maxPoolSize,则根据任务拒绝策略进行拒绝。

6-ThreadLocal中Map的key为什么是弱引用?

  • 为什么说不清理自定义的 ThreadLocal 变量会导致内存泄露呢?

相互之间的关系,这块最好能够手绘出来,这样既体现你对其的理解,一定程度上也能够体现你代码设计能力。

Thread Ref → Current Thread → ThreadLocalMap → Entry → Value

线程对象存活以上链路的引用关系就会一直存在,如果该线程执行耗时任务,线程一直存活,那么当GC进行可达性分析的时候,由于 Value 是可达的,无法回收。如果业务逻辑已经完成处理,这时就不再需要这个 Value,但是由于其一直未被清理,此时也就发生了内存泄漏问题。

小结

本文属于对所提问题的要点阐述,如果你能在这些得分点的基础上回答的更加完善,面试在我这绝对是加分项,并且我相信大多数面试官也是如此。


相关文章
|
Python
【Python面试】 说说Python中pass的作用?
最近公众号新增加了一个栏目,就是每天给大家解答一道Python常见的面试题,反正每天不贪多,一天一题,正好合适,只希望这个面试栏目,给那些正在准备面试的同学,提供一点点帮助! 小猿会从最基础的面试题开始,每天一题。如果参考答案不够好,或者有错误的话,麻烦大家可以在留言区给出自己的意见和讨论,大家是要一起学习的 。
113 0
【Python面试】 说说Python中pass的作用?
|
30天前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
1月前
|
Java 编译器 C++
【Java基础面试一】、为什么Java代码可以实现一次编写、到处运行?
这篇文章解释了Java能够实现“一次编写,到处运行”的原因,主要归功于Java虚拟机(JVM),它能够在不同平台上将Java源代码编译成的字节码转换成对应平台的机器码,实现跨平台运行。
【Java基础面试一】、为什么Java代码可以实现一次编写、到处运行?
|
1月前
|
Java
【Java基础面试四】、介绍一下Java的数据类型
这篇文章介绍了Java的数据类型,包括8种基本数据类型(整数、浮点、字符、布尔)和3类引用数据类型(数组、类、接口),并提供了基本数据类型所占内存空间和数据范围的详细信息。
|
1月前
|
Java C++
【Java基础面试十七】、Java为什么是单继承,为什么不能多继承?
这篇文章讨论了Java单继承的设计原因,指出Java不支持多继承主要是为了避免方法名冲突等混淆问题,尽管Java类不能直接继承多个父类,但可以通过接口和继承链实现类似多继承的效果。
【Java基础面试十七】、Java为什么是单继承,为什么不能多继承?
|
1月前
|
Java
【Java基础面试三】、说一说你对Java访问权限的了解
这篇文章介绍了Java中的四种访问权限:private、default(无修饰符时的访问权限)、protected和public,以及它们分别在修饰成员变量/方法和类时的不同访问级别和规则。
【Java基础面试三】、说一说你对Java访问权限的了解
|
1月前
|
Java
【Java基础面试二】、个Java文件里可以有多个类吗(不含内部类)?
这篇文章讨论了Java文件中类的定义规则,指出一个Java文件可以包含多个类(不包含内部类),但其中最多只能有一个public类,且如果有public类,它的名称必须与文件名一致。
|
30天前
|
XML 存储 JSON
【IO面试题 六】、 除了Java自带的序列化之外,你还了解哪些序列化工具?
除了Java自带的序列化,常见的序列化工具还包括JSON(如jackson、gson、fastjson)、Protobuf、Thrift和Avro,各具特点,适用于不同的应用场景和性能需求。
|
30天前
|
Java
【Java基础面试三十七】、说一说Java的异常机制
这篇文章介绍了Java异常机制的三个主要方面:异常处理(使用try、catch、finally语句)、抛出异常(使用throw和throws关键字)、以及异常跟踪栈(异常传播和程序终止时的栈信息输出)。
|
30天前
|
Java
【Java基础面试三十八】、请介绍Java的异常接口
这篇文章介绍了Java的异常体系结构,主要讲述了Throwable作为异常的顶层父类,以及其子类Error和Exception的区别和处理方式。