1. 传输层协议及使用场景
-
TCP:面向连接、可靠传输、保证数据顺序与完整性,适用于对数据准确性要求高的场景,如文件传输、Web请求(HTTP/HTTPS)。
-
UDP:无连接、低延迟、不保证顺序与可靠性,适用于实时性要求高、可容忍少量丢包的场景,如实时音视频、DNS查询、游戏数据同步。
2. 多线程使用场景与线程数估算
-
使用场景:
-
高并发请求处理
-
定时任务与异步任务处理
-
计算密集型任务的并行计算
-
IO密集型任务的重叠执行
-
生产者-消费者模型
-
-
线程数估算:
-
CPU密集型任务:
线程数 = CPU核心数 + 1
-
IO密集型任务:
线程数 = CPU核心数 × (1 + 平均IO等待时间 / CPU计算时间)
-
-
判断标准:
-
CPU利用率低于50%时,可适当增加线程数
-
CPU利用率高于90%时,应减少线程数或优化代码
-
任务队列持续积压导致延迟上升时,需扩容线程池
-
线程数不得超过操作系统限制(如Linux默认每进程1024线程)
-
3. 线程池的提交方式
方法 | 返回值 | 说明 |
---|---|---|
execute(Runnable command) |
void | 提交Runnable任务,无返回值 |
submit(Callable<T> task) |
Future<T> |
提交Callable任务,返回Future对象 |
submit(Runnable task) |
Future<?> |
提交Runnable任务,返回Future对象 |
submit(Runnable task, T result) |
Future<T> |
提交Runnable任务并指定返回结果 |
4. 锁的实现原理
-
硬件层面:通过CPU原子指令(如CAS、LL/SC)保证操作的原子性。
-
操作系统层面:利用互斥量(mutex)或自旋锁(spinlock)实现线程的阻塞与唤醒。
-
JVM层面:
-
synchronized基于对象头的Mark Word和Monitor实现
-
ReentrantLock基于AQS(AbstractQueuedSynchronizer)队列管理线程竞争
-
-
锁升级机制:偏向锁 → 轻量级锁 → 重量级锁,逐级升级以优化性能
-
优化策略:锁消除、锁粗化、读写分离
-
分布式锁:Redis、ZooKeeper实现跨进程锁,需解决一致性问题
5. TCP拥塞控制的主要作用
通过慢开始、拥塞避免、快重传、快恢复等算法,防止网络中数据量过大导致网络拥塞崩溃,动态调整发送窗口大小,保证网络稳定性与传输效率。
6. String常用函数(列举10个)
-
charAt(int index)
-
contains(CharSequence s)
-
endsWith(String suffix)
-
equals(String another)
-
length()
-
replace(char oldChar, char newChar)
-
substring(int beginIndex, int endIndex)
-
split(String regex)
-
valueOf(int i)
-
concat(String str)
7. String、StringBuffer与StringBuilder的区别
特性 | String | StringBuffer | StringBuilder |
---|---|---|---|
可变性 | 不可变 | 可变 | 可变 |
线程安全 | 安全(不可变天然安全) | 安全(方法同步) | 不安全 |
使用场景 | 字符串常量、作为Map的key | 多线程环境下字符串拼接 | 单线程环境下字符串拼接 |
-
内部实现原理 :三者底层均为
char[]
,StringBuffer与StringBuilder在容量不足时进行动态扩容(默认扩容为原容量的2倍+2)。 -
优势:StringBuffer与StringBuilder通过动态扩容减少频繁创建新对象的开销,提高效率。
8. String字符串的不可变具体指什么?
-
内容不可变:字符串对象创建后,其内容(字符数组)不可修改。
-
内存地址不可变:字符串对象在内存中的地址不可变,任何修改操作都会创建新的字符串对象。
9. HTTP协议常见字段(列举3个)
-
Content-Type
:指定请求或响应的媒体类型,告诉服务器或客户端如何解析数据。 -
User-Agent
:标识客户端软件信息,服务器可根据此字段返回适配内容。 -
Cookie
:由服务器设置,客户端后续请求自动携带,用于维持会话状态。
10. Java异常体系
-
受检异常(Checked Exception) :编译器强制要求处理,如
IOException
、SQLException
。 -
非受检异常(Unchecked Exception) :运行时异常,编译器不强制处理,如
NullPointerException
、ArrayIndexOutOfBoundsException
。 -
错误(Error) :严重系统级问题,程序通常无法恢复,如
OutOfMemoryError
、StackOverflowError
。
11. Java反射获取类信息的三种方式
-
Class.forName("全限定类名")
-
类名.class
-
对象.getClass()
12. Java代理方式及使用场景
-
静态代理:代理类在编译期确定,手动编写代理类。
-
动态代理:运行时动态生成代理类,如JDK动态代理、CGLIB代理。
-
使用场景:
-
AOP(面向切面编程):日志、事务、权限控制
-
RPC(远程过程调用):客户端代理远程服务接口
-
13. equals()方法的作用及重写注意事项
-
作用:默认实现比较两个对象的引用是否指向同一内存地址,重写后通常用于比较对象的内容是否相等。
-
重写注意事项:
-
必须同时重写
hashCode()
方法,保证相等的对象具有相同的哈希码 -
满足自反性、对称性、传递性、一致性
-
重写后需确保
equals()
与hashCode()
逻辑一致,避免在哈希集合中出现逻辑错误
-
14. Java参数传递方式
-
Java采用值传递:
-
基本类型:传递值的副本,修改副本不影响原值
-
引用类型:传递引用的副本(指向对象的地址),修改副本指向的对象内容会影响原对象,但修改副本本身(指向新对象)不影响原引用
-
-
引用传递:方法调用时传递的是变量的原始引用(别名),修改参数直接影响原变量(Java不支持)
-
支持引用传递的语言 :C++(通过引用符号
&
)、C#(通过ref
/out
关键字)
15. Java类初始化顺序(含继承)
-
单个类初始化顺序:
-
静态变量和静态代码块(按书写顺序)
-
实例变量和实例代码块(按书写顺序)
-
构造器
-
-
存在继承时的初始化顺序:
-
父类静态变量和静态代码块
-
子类静态变量和静态代码块
-
父类实例变量和实例代码块
-
父类构造器
-
子类实例变量和实例代码块
-
子类构造器
-
16. 本地方法栈的作用
用于支持native方法的执行,保存native方法的局部变量、参数、返回值,并管理native方法的调用过程。
17. Java双亲委派机制
-
机制描述:
-
类加载器收到加载请求时,先不自行加载,而是委托给父加载器
-
父加载器检查是否已加载该类,若已加载则直接返回
-
若未加载,继续向上委托,直到顶层启动类加载器
-
若顶层加载器无法加载,子加载器才尝试自行加载
-
-
目的:避免类的重复加载,保证核心类库的安全性(防止核心类被篡改)
18. 重写与重载的区别
表格
复制
区别维度 | 重写(Override) | 重载(Overload) |
---|---|---|
发生范围 | 子类与父类之间 | 同一个类内部 |
方法签名 | 方法名、参数列表相同 | 方法名相同,参数列表不同 |
返回类型 | 可协变 | 可不同 |
访问权限 | 不能严于父类 | 无限制 |
19. 子类构造方法调用父类构造方法的注意事项
-
子类构造方法中调用父类构造方法时,必须位于第一行 ,使用
super()
或super(参数)
显式调用 -
若未显式调用,编译器默认调用父类无参构造器;若父类没有无参构造器,编译报错
20. 子类实例初始化是否会触发父类实例初始化?
会。子类实例化前,必须先完成父类的实例初始化(包括实例变量、实例代码块、构造器)。
21. instanceof关键字的作用
用于判断对象是否为指定类或其子类的实例,或是否实现了指定接口,返回boolean值。
22. 强制类型转换注意事项
-
基本类型强制转换:
- 大范围类型转小范围类型(如double转int)可能丢失精度或溢出
-
引用类型强制转换:
-
只能将父类引用转换为子类引用(向下转型),且实际对象必须是子类实例,否则抛出
ClassCastException
-
转换前建议使用
instanceof
进行类型检查
-
23. Java中的重入锁
-
常见重入锁:
-
synchronized
关键字(隐式重入锁) -
ReentrantLock
类(显式重入锁)
-
-
重入锁的意义:允许同一个线程多次获取同一把锁,避免嵌套同步代码块时发生死锁,提高代码灵活性和可读性
24. 指令重排序的优点与原因
-
优点:
-
提高CPU指令并行度
-
隐藏内存访问延迟
-
优化缓存利用率
-
-
原因:
-
编译器优化(指令重排)
-
CPU乱序执行(流水线技术)
-
内存层级缓存延迟
-
25. Arrays.sort()内部原理
-
基本类型数组 :使用双轴快速排序(Dual-Pivot Quicksort)
-
对象类型数组 :使用TimSort(归并排序与插入排序的混合优化算法,稳定排序)
26. 堆排序复杂度
-
时间复杂度:O(n log n)
-
空间复杂度:O(1)(原地排序)
27. 字符串"asdasjkfkasgfgshaahsfaf"哈夫曼编码后的比特数
经过哈夫曼编码后,该字符串存储所需比特数为 56位。
28. CPU高速缓存的优缺点
-
优点:
-
访问延迟低(纳秒级)
-
提高并发性能
-
减少CPU空闲等待
-
降低内存带宽压力
-
-
缺点:
-
容量有限
-
缓存一致性协议(如MESI)可能引入延迟
-
缓存未命中时性能下降明显
-
29. Java线程安全类举例
-
StringBuffer
:线程安全的可变字符串 -
ConcurrentHashMap
:线程安全的哈希表 -
Vector
:线程安全的动态数组(已过时,推荐使用ArrayList
+同步包装类)
30. LRU算法描述
Least Recently Used(最近最少使用)缓存淘汰策略:
-
新访问的数据移动到缓存头部
-
重复访问的数据也移动到头部
-
缓存满时淘汰尾部最久未使用的数据
30. Spring Bean 容器 vs. Spring IoC 容器
Q:二者到底有什么区别?
维度 | Spring Bean 容器 | Spring IoC 容器 |
---|---|---|
本质 | 运行时实体,真正干活的容器 | 设计思想,一种理念 |
职责 | 负责 Bean 的创建、依赖注入、生命周期管理(初始化、销毁、作用域等) | 定义"谁控制谁"------由框架而非程序员控制对象创建与依赖 |
举例 | ApplicationContext 、BeanFactory 的具体实现类 |
"控制反转"思想本身 |
关系 | 是 IoC 思想的具体实现 | 是 Bean 容器背后的指导思想 |
IoC 通过反转控制权,降低组件之间的耦合度,提高可维护性与可测试性。
31. 如何理解 Spring IoC(控制反转)?
一句话定义
把"对象创建、依赖查找、生命周期管理 "的掌控权从业务代码 反转 给 Spring 框架,开发者只关心业务逻辑,不关心对象如何实例化、如何装配。
三个关键点
-
谁控制谁:框架控制应用程序所需对象的生命周期。
-
为何反转 :传统方式由程序主动
new
对象,IoC 改为由容器被动注入(DI)。 -
带来的好处:
-
降低耦合:业务类只依赖接口而非实现
-
提高可测试性:便于 Mock 与单元测试
-
统一配置:通过 XML、注解或 JavaConfig 集中管理
-