38 归档分页
370 留言互动
4 核心专题

面试现场【List篇】

List是Java集合接口,常用实现ArrayList(数组,查询快,容量不足时按1.5倍扩容)和LinkedList(链表,增删快)。ArrayList适合读多写少,LinkedList适合写多读少。List可重复有序,Set不重复无序且基于Map。Vector已少用,线程安全List可用Collections.synchronizedList或CopyOnWriteArrayList;后者写时复制实现并发读,但占内存多且读到旧数据。排序用list.sort或Collections.sort,遍历删除用Iterator.remove或list.removeIf避免fast‑fail。

Redis分布式锁的七种方案

Redis 常用于实现分布式锁,可靠的锁应具备互斥、超时释放、可重入、高性能、高可用和安全性。文中系统梳理了七种实现方式:① SETNX + EXPIRE,操作不原子易导致死锁;② SETNX + 时间戳值,需客户端时间同步且仍缺唯一标识;③ Lua 脚本一次性完成 SETNX 与 EXPIRE,保证原子性;④ SET EX PX NX 直接原子加锁;⑤ 在 value 中存唯一随机标识并用 Lua 脚本校验后删除,防止误删;⑥ Redisson 框架通过 watchdog 自动续期解决锁提前失效问题;⑦ Redlock 多节点算法,在多数 Redis master 上同时加锁并校时,提升跨节点的安全性。每种方案的优缺点和适用场景均有阐述。

面试现场【多线程篇】

面试围绕多线程展开,阐述使用多线程提升资源利用率和并发能力的原因及适用场景,如大文件读写、耗时任务和定时任务。解释线程安全的含义,并给出常用解决方案:原子类、CountDownLatch、并发集合、synchronized、Lock 及分布式锁。说明 synchronized 通过 monitorenter/monitorexit 实现锁机制及其字节码标志。比较 synchronized 与 ReentrantLock 的锁释放方式、可公平性、可中断性、超时获取和 tryLock。简述公平锁概念并介绍 CAS 的工作原理及在 AtomicInteger 中的应用。

面试现场【Redis篇】

Redis 4.0 前单线程处理网络 I/O 与 Set/Get,避免锁竞争并使用 epoll 实现高效 I/O;4.0 后引入多线程用于大数据异步删除。持久化提供 AOF(追加日志)和 RDB(快照)两种方式,4.0 还支持二者混合。AOF 先执行命令再写日志,存在数据丢失和阻塞风险;RDB 可通过 save 同步阻塞或 bgsave 子进程异步生成快照,写时复制保证数据可修改。高可用方案包括主从复制、哨兵自动故障转移和 Cluster。Cluster 将键映射至 16384 个哈希槽,采用 CRC16 取模实现节点选择,解决写和存储扩展问题。

每日一题(2022/1/20)

代码演示了 Java 中字符串比较的细节。`s1` 通过 `new String("xiaozou")` 在堆中创建了独立对象,`s2` 直接引用常量池中的字面量,两者地址不同,`s1 == s2` 为 `false`。调用 `s1.intern()` 时,若常量池已有相同内容的字符串,则返回该池中对象的引用,否则将其加入池中。因为常量池已经存在 `"xiaozou"`,`s3` 获得的正是 `s2` 的引用,故 `s2 == s3` 为 `true`。文章通过源码解释说明了 `intern()` 的工作原理及其在字符串共享中的作用。

每日一题(2022/1/19)

本文给出一道面试题:在保持 `String s` 引用不变的前提下,使其输出从 `abc` 变为 `abcd`。常规做法如 `StringBuilder.append()` 或 `String.replace()` 均不可行。正确方案是通过反射修改 `String` 的内部 `value`(char[])字段:获取字段、设为可访问、写入新字符数组即可。但在 JDK 11 及以上运行时会抛出 `IllegalArgumentException`,因为 `value` 为 `final` 且受模块系统的非法反射访问限制。文章说明了 `setAccessible(true)` 的作用并解释异常产生的原因。

Dubbo最佳实战

Dubbo是高性能的 Java RPC 框架,官方推荐使用 Zookeeper 作为服务注册中心。文章先概述 Dubbo 的特性与服务治理,随后通过一个基于 Maven 的完整实战案例演示其使用流程:①创建 service‑api 模块定义公共接口;②在 provider 模块引入该接口并实现类,用 @Service 注解将服务注册到 Zookeeper;③在 consumer 模块同样引入接口,通过 @Reference 调用服务。文中提供了所有 Maven 依赖、properties 配置、启动代码以及运行步骤(启动本机 Zookeeper、启动提供者、启动消费者,回车键触发调用),完整源码已上传至 GitHub。

使用HashMap的注意事项

HashMap 的键必须唯一,插入相同键会覆盖旧值。键唯一性的判断先比较 hashCode,再通过 equals 判断真实相等。因此在自定义类作键时必须同时重写 hashCode 与 equals。HashMap 底层结构为数组+链表,JDK 8 之后在链表过长时会转为红黑树;它是非线程安全的,键和值均可为 null,键唯一而值可以重复。本文通过 String 与自定义 Person 类的示例,演示了未重写方法导致键重复的现象,并给出正确实现的代码示例。

数据结构之线性表详解

本文系统阐述了线性表的三种基本实现。首先介绍数组:连续内存存储,支持 O(1) 随机读写,插入/删除需搬移元素导致 O(n) 时间,需扩容且空间必须连续,广泛用于 ArrayList、Redis 等。随后讲解链表:节点通过指针链接,采用随机存储,可灵活插入、删除,时间复杂度均为 O(1)(查找为 O(n)),不受连续空间限制,适用于树、图、LRU 等。最后简述栈的概念及其数组、链表两种实现,强调后进先出特性及 push、pop 操作。文中对比了数组和链表的优缺点,指出读多写少适合数组,频繁插删适合链表。整体呈现线性表的存储原理、操作实现、复杂度分析及典型应用场景。