岗位索引

后端开发工程师面试题库第 4 页

后端开发面试题解析,覆盖缓存、数据库、分布式和系统设计基础。

378 道题 15 个公司 134 个知识点

后端开发相关面试题第 4 页

怎么看待Java和Go的后端开发?

这道题考察的不是候选人是否偏爱 Java 或 Go,而是能否从后端工程的完整生命周期判断技术选型:语言生态、运行时模型、并发能力、性能与 GC、部署形态、可观测性、团队成熟度、业务适配和迁移风险。高质量回答应避免“Java 老、Go 快”这类简单结论,而是说明两者各自擅长的场景,以及在真实系统中如何做渐进式选型。

go和java的接口有什么不同?

Go 和 Java 的接口都用于抽象行为,但核心模型不同:Java 接口是名义类型系统的一部分,类需要显式声明实现关系;Go 接口是结构化类型系统的一部分,只要类型的方法集满足接口要求,就自动实现接口。这个差异会进一步影响方法匹配、接收者规则、空值语义、泛型约束、运行时派发方式以及工程设计风格。

Java 线程池的核心参数和执行流程是什么?

这道题考察的不是背出几个构造参数,而是要说明 ThreadPoolExecutor 如何用线程数、队列、线程工厂和拒绝策略共同定义资源边界。高质量回答应先点明线程池复用线程、控制并发、削峰和保护系统的目的,再按任务提交后的执行路径解释:先看核心线程,再入队,再扩容到最大线程,最后触发拒绝策略,同时补充队列选择、参数取舍、异常处理、关闭流程和线上监控。

java中的锁有哪些?

Java 中的锁不能只回答 synchronized 和 ReentrantLock,而要按实现机制、语义特征、等待方式、读写模型和 JVM 优化层级来拆解。面试时应从对象监视器、AQS 显式锁、读写锁、StampedLock、CAS 原子类、LockSupport 与 Condition 这些核心工具出发,再说明乐观/悲观、公平/非公平、可重入/不可重入、自旋/阻塞等分类维度,并结合适用场景、性能取舍和常见陷阱给出判断依据。

JVM 垃圾回收机制是什么?

JVM 垃圾回收机制的核心,是 JVM 自动识别已经不可达的对象并回收其占用的内存,从而降低手动释放内存的负担。面试回答要先明确:GC 主要发生在 Java 堆,尤其是新生代;同时也要补充方法区或元空间在类卸载、常量废弃时也可能被回收,但虚拟机栈、本地方法栈和程序计数器通常随线程或栈帧生命周期自动释放,不是 GC 的主要战场。

JVM中的【堆】是用什么数据结构来实现的?

JVM 中的堆不是二叉堆、最大堆、最小堆这种数据结构,而是 JVM 运行时用于存放对象实例和数组的一块共享内存区域。它的具体组织方式取决于垃圾收集器:可能按年轻代、老年代划分,也可能按 Region 管理;对象分配通常依赖 TLAB、指针碰撞、空闲列表等机制,而对象回收依赖可达性分析和 GC 元数据。

JVM 运行时内存区域如何划分?

JVM 运行时内存区域可以按线程私有和线程共享来划分:程序计数器、虚拟机栈、本地方法栈属于线程私有;堆和方法区属于线程共享。面试回答不能只背名称,还要说明每块区域存什么、生命周期如何、会抛什么错误、和垃圾回收的关系,以及 JDK 8 以后永久代被元空间替代这一常见边界。

JVM 如何判断对象可以被回收,分代收集如何工作?

这道题核心不是背垃圾收集器名称,而是说明 JVM 如何从“对象是否还可被程序使用”推导出“是否可回收”,再解释为什么堆会按年轻代和老年代组织。回答时要把可达性分析、GC Roots、引用强度、finalize 的特殊边界,以及 Minor GC、Major GC、Full GC、对象晋升和跨代引用处理串成一条完整链路。

设计一个线程安全的HashMap?

设计线程安全的 HashMap,核心不是简单给每个方法加 synchronized,而是先明确一致性、吞吐量、内存、迭代语义等需求边界,再选择合适的锁粒度和扩容协调方案。一个可落地的设计通常会从桶级锁或分段锁出发,保证单个 key 的 put、get、remove 线性化,同时通过安全发布、volatile、CAS、锁顺序和 resize 协议避免数据丢失、死锁、读到半迁移结构等问题;如果追求工业级性能和复杂场景,通常应优先使用 ConcurrentHashMap,而不是自行实现。

ConcurrentHashMap 为什么能保证线程安全?

ConcurrentHashMap 的线程安全不是靠一个全局大锁实现的,而是把可见性、原子性和局部互斥组合起来:数组槽位和节点关键字段用 volatile 保证可见性,空桶插入、初始化和扩容状态切换用 CAS 保证原子更新,非空桶写入时只锁住单个桶的头节点,读操作基本无锁;再配合扩容协作、红黑树化和分散计数,既保证并发访问下结构不被破坏,又尽量降低锁竞争。

java中有哪些以队列、链表为底层实现的数据结构?

Java 里要区分“队列接口”和“链表底层”。Queue、Deque 是行为抽象,表示先进先出、双端队列或优先级访问;LinkedList、ConcurrentLinkedQueue、LinkedBlockingQueue 这类才是链式节点结构。ArrayDeque、ArrayBlockingQueue、PriorityQueue 虽然暴露队列接口,但底层分别是循环数组、有界数组和二叉堆数组,不是链表。LinkedHashMap 则是哈希表加双向链表,用链表维护插入顺序或访问顺序,但它本身不实现 Queue。

怎么保证map的线程安全?

保证 Map 线程安全的核心是先明确并发语义:是只要单次 get/put 安全,还是复合操作也要原子;是允许弱一致迭代,还是必须看到稳定快照;是读多写少、写多读少,还是配置类读多且整体替换。常见方案包括外部加锁、Collections.synchronizedMap、ConcurrentHashMap、不可变 Map、读写锁和快照/COW。面试中不能只说“用 ConcurrentHashMap”,还要说明它解决了什么、不解决什么,以及复合操作、迭代一致性、内存可见性和选型边界。

什么是线程安全?

线程安全指一段代码、对象或组件在多个线程同时访问时,仍然能够保持预期的正确性,不因为执行时序交错而产生脏数据、丢失更新、状态破坏或偶发异常。判断线程安全不能只看单次调用是否正确,而要看共享可变状态在并发读写下是否满足原子性、可见性和有序性,并通过不可变、线程封闭、同步、原子类或并发容器等手段建立可靠的并发语义。

如何在实际中判断是否会出现线程安全问题?

判断实际项目中是否会出现线程安全问题,核心不是先看有没有多线程,而是追踪共享可变状态是否被多个执行路径并发访问,以及访问是否包含读改写、检查后执行、跨字段一致性、对象发布等风险。实战判断要结合代码审查、并发入口梳理、锁边界分析、压测和线上偶发症状,而不是依赖一次本地复现。

单例模式如何实现,如何保证线程安全?

单例模式的核心目标是让一个类在进程内只暴露一个可访问实例,并控制实例创建时机。回答时应从构造器私有化、全局访问点、线程安全发布、延迟加载、反射和序列化破坏边界几个维度展开。常见实现包括饿汉式、同步懒汉式、双重检查锁、静态内部类和枚举单例,其中推荐优先说明静态内部类和枚举单例,再解释为什么双重检查锁必须配合 volatile。

如果要用线程安全的数据结构,有什么替代方案?

使用线程安全数据结构时,核心不是简单把 ArrayList、HashMap 换成带锁版本,而是先判断共享状态是否真的必须共享,再按读写比例、是否需要阻塞、是否需要顺序、是否有复合操作一致性来选型。Java 中常见替代方案包括 ConcurrentHashMap、CopyOnWriteArrayList、BlockingQueue、ConcurrentLinkedQueue、同步包装器、不可变快照、ThreadLocal、分段锁、Actor 或消息队列串行化,以及在跨进程场景下使用数据库或缓存的原子能力。

内核多线程模块的线程调度是怎么实现的?

Linux 内核多线程模块的线程调度通常不是模块自己实现调度器,而是模块创建多个内核线程后交给 Linux 统一调度。每个内核线程都有 task_struct,进入某个调度类,挂到 CPU 运行队列上,由 CFS、实时调度类或其他调度类根据状态、优先级、vruntime、CPU 负载和亲和性决定何时运行、抢占、阻塞、唤醒和上下文切换。模块开发者更关注线程创建、等待唤醒、停止退出、锁边界和不可睡眠上下文。

如何创建子进程?

创建子进程的核心方式是调用 fork():内核复制当前进程的进程描述信息,创建一个几乎相同但 PID 不同的新进程;父进程得到子进程 PID,子进程得到返回值 0。典型工程模式是 fork 后,子进程按需执行 exec 系列函数加载新程序,父进程使用 wait 或 waitpid 回收子进程退出状态,避免僵尸进程。Linux 中 fork 并不会立即完整拷贝父进程全部内存,而是依赖写时复制降低成本。面试回答应同时说明资源继承、文件描述符共享语义、信号处理、孤儿和僵尸进程、vfork 与 posix_spawn 的使用边界,以及多线程服务中 fork 后的工程风险。

常用的Linux指令有哪些?

这道题不适合只背命令清单,面试官更关注候选人是否能把 Linux 指令放进真实后端排障场景中:如何定位文件、查看日志、过滤文本、观察进程、确认端口、检查磁盘、调整权限、串联管道并形成稳定的排查路径。好的回答应按使用场景分类,并能说明每类命令解决什么问题、常见参数怎么用、出现异常时下一步怎么验证。

Linux 中如何用管道命令排查日志?

这类 Linux 日志排查题考察的不是背命令,而是能否在生产环境中安全、快速、可复现地定位问题。核心思路是先限定日志范围,再用管道逐步缩小:时间窗口、关键字、traceId、状态码、接口路径、调用方、异常栈,最后用统计命令判断问题规模和集中点。回答时要体现两个能力:一是熟练组合 tail、grep、awk、sed、sort、uniq、wc、xargs、less、journalctl;二是知道大文件、线上机器、权限、性能和误操作风险。

LRU 算法在操作系统中如何使用?

LRU 的核心思想是淘汰最近最少被访问的数据,在操作系统里主要用于页面置换、页缓存回收和内存压力下的缓存管理。但真正的系统通常不会实现严格 LRU,而是借助访问位、脏页状态、Clock、二次机会、活跃/非活跃链表等机制近似判断冷热,以降低维护成本并兼顾吞吐、延迟和写回开销。

在Linux里删除当前目录下七天前创建的所有文件会用到哪些命令?

核心命令通常是 find,用它限定当前目录、文件类型和时间条件,再用 -delete 或 -exec rm 执行删除。面试时要特别说明:Linux 中常用的 find -mtime 判断的是“修改时间”,不是严格意义上的“创建时间”;如果题目口语里说“七天前创建”,生产环境通常需要先确认到底是按创建时间、修改时间,还是业务生成时间清理。

知道如何查看线程的cpu内存等资源使用情况吗?

查看线程级 CPU、内存等资源使用情况,核心思路是先确认进程 PID,再进入线程维度观察。Linux 中线程本质上是轻量级进程,每个线程都有自己的 TID,因此可以用 top -H、ps -L、pidstat -t、/proc/<pid>/task/<tid>/ 等方式查看线程级 CPU、调度状态、上下文切换和栈。CPU 通常能定位到线程,但内存大多是进程级共享资源,不能简单拆给单个线程。

分表规则中,跨表查询+分页该怎么做?

跨表查询和分页的核心不是把单表 limit offset 原样套到每个分表,而是先判断能否命中分片键;能命中就路由到单表或少量表,不能命中才考虑广播查询、局部排序、全局归并。深分页会被分片数放大,工程上更推荐游标分页、二级索引表、异步宽表或搜索服务承接全局查询。

fork发生复制的时候子进程会复制什么?

fork 的本质不是把父进程的一切都物理复制一份,而是创建一个几乎相同的子进程执行上下文:内核为子进程建立新的进程描述符、PID、虚拟地址空间视图和资源引用关系;用户态内存通常通过写时复制延迟分裂;文件描述符表被复制但底层打开文件对象常被共享。因此面试回答要区分“逻辑复制”“引用共享”和“写时复制后才真正复制”。

线程最大数量和什么有关?

Linux 下线程最大数量不是一个固定常量,而是由多层约束共同决定:系统级的 threads-max 和 pid_max、用户级的 RLIMIT_NPROC、服务或容器的 pids 限制、单进程可用地址空间、物理内存与 overcommit 策略、每个线程的用户栈和内核对象开销,以及语言运行时的栈配置共同取最小值。能创建多少线程是一回事,系统能否高效调度这些线程又是另一回事。

Kafka 为什么吞吐量高?

Kafka 的高吞吐不是单点优化,而是围绕日志追加模型构建的一整套链路设计:生产端批量发送和压缩降低请求次数与网络字节数,Broker 端用顺序写和 Page Cache 减少随机磁盘 IO,发送文件时利用零拷贝降低用户态与内核态拷贝成本,Topic 分区让读写并行扩展,消费者拉取模型让消费端按自身能力批量读取。同时,ISR、acks、副本数、刷盘策略等可靠性配置会影响吞吐,面试中要讲清这些设计如何共同减少 IO、网络、CPU 和锁竞争开销。

Http 报文里有什么?

HTTP 报文是客户端和服务端交换应用层数据的基本格式。HTTP/1.x 报文由起始行、请求头或响应头、空行、消息体组成。请求报文的起始行叫请求行,包含方法、请求目标和协议版本;响应报文的起始行叫状态行,包含协议版本、状态码和原因短语。头部字段描述元信息,空行分隔头部和消息体,消息体承载实际业务数据。

http 协议 转 dubbo 协议怎么做的?

HTTP 转 Dubbo 的本质不是协议字节直接翻译,而是在网关或适配层把一个 HTTP 请求解析成一次 Dubbo RPC 调用。核心流程是:接收 HTTP 请求,按路由规则定位 Dubbo 接口、方法和版本,完成参数绑定和类型转换,通过注册中心或本地配置找到服务提供者,使用 Dubbo 客户端按 Dubbo 协议编码、序列化并发起调用,再把 Dubbo 响应、异常和超时结果转换成 HTTP 状态码与响应体。回答要围绕映射、发现、调用、治理和观测展开,而不是只说用网关转发。

设计朋友圈功能时,数据库表如何从简单到复杂演进?

朋友圈数据库设计可以按复杂度分层回答:最小可用版本先有用户、好友关系、动态、媒体、评论和点赞;进阶版本补可见范围、权限校验和删除模型;高并发版本再讨论时间线、读扩散与写扩散、冷热数据、索引、分库分表、幂等与一致性。面试时不要一上来就堆表,而是先说明业务读写路径:发动态、刷列表、看详情、评论点赞、删除和权限变化。