面试概况
本次面试为快手商业化部门日常实习生的一轮面试,面试时长约为40分钟。面试内容主要集中在Java基础知识、数据库、并发编程、算法等方面。以下是详细的面试问题及回答整理。
面试问题及回答
1. Java 的集合类知道哪些?
Java 的集合类主要分为以下几类:
- List:有序集合,允许重复元素。常见实现类有
ArrayList
、LinkedList
、Vector
。 - Set:不允许重复元素的集合。常见实现类有
HashSet
、LinkedHashSet
、TreeSet
。 - Map:键值对集合,键唯一但值可以重复。常见实现类有
HashMap
、LinkedHashMap
、TreeMap
、Hashtable
、ConcurrentHashMap
。 - Queue:队列集合,支持 FIFO(先进先出)操作。常见实现类有
LinkedList
、PriorityQueue
、ArrayDeque
。
2. 说说 HashMap?
HashMap
是 Java 中常用的集合类,基于哈希表实现,允许存储键值对。其主要特点如下:
- 无序存储:
HashMap
不保证元素的顺序。 - 允许空键和空值:但最多只能有一个空键。
- 线程不安全:在多线程环境下使用
HashMap
可能会导致数据不一致。 - 时间复杂度:插入、删除、查找操作的时间复杂度均为 O(1)(理想情况下)。
3. HashMap 线程安全吗,如何变线程安全?
HashMap
本身是线程不安全的。可以通过以下几种方式使其线程安全:
使用
Collections.synchronizedMap
:将HashMap
包装成线程安全的Map
。Map<String, String> map = Collections.synchronizedMap(new HashMap<>());
使用
ConcurrentHashMap
:ConcurrentHashMap
是线程安全的Map
实现,性能优于Hashtable
。Map<String, String> map = new ConcurrentHashMap<>();
手动同步:在访问
HashMap
的地方手动加锁。synchronized (map) { map.put(key, value); }
4. ConcurrentHashMap 如何实现的?
ConcurrentHashMap
通过分段锁(Segment)机制实现线程安全。具体实现如下:
- 分段锁:将整个哈希表分成多个段(Segment),每个段内部是一个小的哈希表。
- 锁粒度:每次操作只锁定当前段,而不是整个哈希表,提高了并发性能。
- JDK 1.8 改进:取消了 Segment,改为使用 CAS 操作和锁竞争机制,进一步提高了性能。
5. synchronized 原理以及升级过程
synchronized
是 Java 中的内置锁,用于实现线程同步。其原理如下:
- 锁的状态:锁有四种状态,依次是无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态。
锁升级:锁可以从较低状态升级到较高状态,但不能降级。
- 无锁状态:没有任何线程持有锁。
- 偏向锁:偏向于第一个获取锁的线程,减少锁的竞争。
- 轻量级锁:使用 CAS 操作尝试获取锁,如果失败则升级为重量级锁。
- 重量级锁:使用操作系统互斥量实现,性能较差。
6. 线程池的参数?
ThreadPoolExecutor
是 Java 中创建线程池的类,其构造方法参数如下:
- corePoolSize:核心线程数。
- maximumPoolSize:最大线程数。
- keepAliveTime:线程空闲时间。
- unit:
keepAliveTime
的时间单位。 - workQueue:任务队列,用于存储等待执行的任务。
- threadFactory:线程工厂,用于创建线程。
- handler:拒绝策略,当任务队列满且线程数达到最大值时的处理策略。
7. full gc, minor gc?
- Minor GC:回收年轻代(Young Generation)的垃圾收集操作。当年轻代空间不足时触发。
Full GC:回收整个堆(包括年轻代和老年代)的垃圾收集操作。通常在以下情况下触发:
- 老年代空间不足。
- 系统显式调用
System.gc()
。 Minor GC
时发现老年代空间不足。
8. 垃圾回收算法?
常见的垃圾回收算法有:
- 标记-清除:标记所有需要回收的对象,然后清除这些对象。
- 标记-整理:标记所有需要回收的对象,然后将存活对象移动到一端,清除边界外的对象。
- 复制:将内存分为两个区域,每次只使用其中一个区域,将存活对象复制到另一个区域。
- 分代收集:将内存分为年轻代和老年代,分别使用不同的回收算法。
9. CPU 密集型和 IO 密集型下如何设置核心线程数?
CPU 密集型:任务主要消耗 CPU 资源,核心线程数一般设置为
CPU 核心数 + 1
。int corePoolSize = Runtime.getRuntime().availableProcessors() + 1;
IO 密集型:任务主要消耗 I/O 资源,核心线程数一般设置为
CPU 核心数 * 2
。int corePoolSize = Runtime.getRuntime().availableProcessors() * 2;
10. 聚簇索引和非聚簇索引区别
聚簇索引:
- 数据行的物理存储顺序与索引顺序一致。
- 一个表只能有一个聚簇索引。
- 查询速度快,但插入、删除、更新操作较慢。
非聚簇索引:
- 数据行的物理存储顺序与索引顺序无关。
- 一个表可以有多个非聚簇索引。
- 查询速度相对较慢,但插入、删除、更新操作较快。
11. MySQL 的各个隔离级别,以及分别解决了什么问题
MySQL 的事务隔离级别有四种:
- 读未提交(Read Uncommitted):最低隔离级别,允许脏读。
- 读已提交(Read Committed):允许不可重复读,但不允许脏读。
- 可重复读(Repeatable Read):默认隔离级别,允许幻读,但不允许脏读和不可重复读。
- 串行化(Serializable):最高隔离级别,不允许脏读、不可重复读和幻读。
12. Redis 有什么数据类型
Redis 支持多种数据类型:
- 字符串(String):最基本的类型,可以存储字符串、数字等。
- 列表(List):有序集合,支持从两端插入和删除操作。
- 集合(Set):无序集合,不允许重复元素。
- 有序集合(Sorted Set):有序集合,每个元素关联一个分数。
- 哈希表(Hash):键值对集合,键唯一。
- 位图(Bitmap):用于处理位级别的操作。
- HyperLogLog:用于估算集合的基数。
13. Redis 分布式锁实现?
Redis 分布式锁可以通过以下几种方式实现:
SETNX 命令:使用
SETNX
命令尝试获取锁。SETNX key value
EXPIRE 命令:设置锁的超时时间,防止死锁。
EXPIRE key seconds
Lua 脚本:使用 Lua 脚本保证原子性。
local key = KEYS[1] local value = ARGV[1] local expire = tonumber(ARGV[2]) if redis.call("setnx", key, value) == 1 then redis.call("expire", key, expire) return 1 else return 0 end
14. 项目中的前缀树,自定义注解限频,网站优化过程
- 前缀树(Trie):用于快速查找字符串,常用于搜索引擎、拼写检查等。
自定义注解限频:通过自定义注解和 AOP 切面实现接口限流。
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface RateLimit { int limit() default 100; int time() default 1; } @Aspect @Component public class RateLimitAspect { @Around("@annotation(rateLimit)") public Object around(ProceedingJoinPoint joinPoint, RateLimit rateLimit) throws Throwable { // 限流逻辑 return joinPoint.proceed(); } }
网站优化过程:
- 前端优化:使用 CDN、压缩资源、合并文件、懒加载等。
- 后端优化:优化数据库查询、使用缓存、减少网络请求等。
- 服务器优化:调整 JVM 参数、优化网络配置、使用负载均衡等。
15. 算法:反转链表
反转链表的实现如下:
public ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode current = head;
while (current != null) {
ListNode next = current.next;
current.next = prev;
prev = current;
current = next;
}
return prev;
}
总结
本次面试涉及的知识点较为广泛,涵盖了 Java 基础、并发编程、数据库、算法等多个方面。准备面试时,建议重点复习这些知识点,并结合实际项目经验进行准备。希望这篇博客对大家有所帮助!
评论 (0)