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

什么是PECS?

PEPS(Producer Extends Consumer Super)是 Java 泛型的核心规则。使用 `? extends T` 表示协变,只能安全读取 T 或其子类元素,不能写入;`? super T` 表示逆变,只能安全写入 T 或其子类,读取时只能得到 Object。文章通过 `List<? extends Fruit>`、`List<? super Fruit>` 示例说明了编译错误的原因,并比较了 Kotlin 中的 `out`(只读)和 `in`(只写)对应关系。还指出数组在 Java 中是协变的,以及 Kotlin 的 `inline` + `reified` 实现了运行时泛型保留。最后总结:读取用 `extends`,写入用 `super`,两者兼顾则不使用通配符。

什么是类型通配符?

类型通配符用于在泛型中表示未知或受限的元素类型。 - `<?>` 表示元素类型未知的 List,是所有具体泛型 List 的父类,但不能向其中写入元素。 - `<? extends T>` 表示元素类型为 T 或其子类的 List,只能读取元素,写入受限。 - `<? super T>` 表示元素类型为 T 或其父类的 List,可安全写入 T 类型元素,读取时只能得到 Object。 文章通过 `GenericDemo` 示例演示了三种通配符的声明方式及合法/非法的赋值情况,帮助理解它们在类型安全和灵活性上的作用。

Redis持久化、主从与哨兵架构

Redis提供RDB快照(save同步、bgsave异步)和AOF日志(appendfsync策略、重写),并可开启混合持久化以加速重启。可用crontab实现定时备份。主从复制使用PSYNC,支持全量/增量同步和断点续传,并可配置只读从节点。Jedis示例展示连接池、Pipeline批量请求及Lua脚本实现原子操作。

JVM垃圾收集器G1&ZGC

G1(-XX:+UseG1GC)将堆划分为约2048个等大小Region,保留但不强制分代,采用复制算法在STW阶段按“回收价值‑成本”优先选择Region,实现可预测的停顿(‑XX:MaxGCPauseMillis),并通过Humongous区专门处理大对象。G1的主要GC类型为Young、Mixed和Full,提供丰富的调优参数以平衡吞吐量和延迟,适合8 GB 以上、停顿要求在 0.5 s 以内的大内存服务器。 ZGC(-XX:+UseZGC)是 JDK 11 引入的低延迟收集器,目标是堆大小任意(TB 级)时仍保持 ≤10 ms 停顿,采用单代、Region(小‑2 MB、 中‑32 MB、 大‑≥4 MB)布局,利用读屏障、颜色指针和自愈转发表实现全并发标记‑整理,并自动感知 NUMA。ZGC 牺牲约 15% 吞吐以换取极短、可预测的停顿,适用于对延迟极为敏感的超大堆应用。

Nacos 注册中心的心跳机制

微服务启动后,内置的 Nacos 客户端每 5 秒向 Nacos 服务器的 /nacos/v1/ns/instance/beat 接口发送一次心跳,携带实例名称、IP、端口、集群、权重等信息。服务器的 naming 模块收到心跳后,先依据 IP+端口判断实例是否已存在;不存在则在实例 Map 中注册;已存在则记录本次心跳时间、标记为健康并推送状态变更消息,随后返回新的心跳间隔。为防止无效实例长期占用,Nacos 每 20 秒扫描实例 Map,将“非健康”实例剔除。这样实现了服务实例的实时注册、健康监测与自动清理。

JVM内存模型深度剖析与优化

本文系统阐述了JVM的整体结构与内存模型,重点解释了Minor GC中对象复制后引用的更新机制——在根扫描阶段记录引用并在对象搬迁后统一指向新地址。随后列举了常用的JVM启动参数(‑Xms、‑Xmx、‑Xmn、‑Xss、‑XX:MetaspaceSize/MaxMetaspaceSize 等)及其含义与调优原则,指出元空间大小调整会触发代价高昂的Full GC,建议将两者设为相同且足够大。通过StackOverflowError 示例说明‑Xss 对线程栈容量和并发线程数的影响。最后给出面向日均百万级订单系统的调优建议:尽量让对象在新生代分配回收,避免频繁晋升至老年代,并为系统预留充足内存,降低GC次数。

选择排序

选择排序把数组划分为已排序和未排序两部分,每轮在未排序区找最小元素并与当前目标位置交换。代码实现中用两层循环,外层 i 为目标索引,内层遍历寻找最小索引 s,最后一次交换即可,已在实现中完成交换次数的优化。时间复杂度与冒泡排序同为 O(n²),但因交换次数少通常更快;若序列已有序度高,冒泡可能更优。选择排序是不稳定的——示例用扑克牌对象演示,同样的键值在不同规则下会改变相对顺序,而冒泡排序保持相对顺序,属于稳定算法。

冒泡排序

冒泡排序通过逐对比较相邻元素并交换,将最大值“冒”到数组末端,重复多轮直至有序。实现思路是外层循环控制轮次,内层比较并在需要时交换,使用布尔变量检测本轮是否有交换以提前结束。代码示例给出简单版和优化版:优化版记录每轮最后一次交换位置,将其作为下一轮的比较上限,当该值为0时直接退出。两版均演示了对数组 `{5,9,7,4,1,3,2,8}` 的排序过程,最终得到有序序列 `[1,2,3,4,5,7,8,9]`。

二分查找

二分查找是一种在有序数组中通过不断取中间元素并与目标值比较、收缩左右边界实现的高效搜索算法。基本思路是设定左、右边界 L、R,循环计算中点 M=(L+R)/2(或使用 M=(L+R)>>>1 防止溢出),比较 A[M] 与目标 T,若相等返回索引,若 A[M]<T 则 L=M+1,若 A[M]>T 则 R=M-1,直至 L>R 表示未找到。文中给出 Java 实现并演示排序后查找示例,同时说明了 (L+R)/2 在极端情况下可能导致整数溢出,推荐使用位右移或分拆加法的写法来避免。