记小菜鸟的第一次面试
前言
时间于2023.11.24,我只身一人前往公司面试。携带着激动与惶恐,同时还有两张简历(doge)。整体面试过程还是很愉快的,面试官是大抵是该公司的技术总监,为人和蔼可亲,父辈年纪。使我局促不安,紧张的情绪消减了不少,但是!依旧没有给后续的面试情况带一点起色(苦笑)。
面试拷问
PS:会附带借鉴网上八股文的答案和自己的理解,如果有误,或者球友有不同见解,希望能够指出,我会好好学习的!
- ArrayList和LinkedList的区别
- 数据结构:ArrayList底层数据结构是动态数组,LinkedList底层是链表(双向链表)
- 应用场景:ArrayList常用语随机查询的时候,LinkedList则是对元素的增加和删除常用
- 控件开销:ArrayList在于需要在列表预留空间,LinkedList开销在于存储节点信息和指针
- 内存占用:ArrayList一般情况下会比LinkedList内存占用小(链表节点存储的信息有数据还有前后驱引用) ps:"ArrayList和LinkedList哪个更占空间?" "一般情况下,LinkedList的占用空间更大,因为每个节点要维护指向前后地址的两个节点,但也不是绝对,如果刚好数据量超过ArrayList默认的临时值时,ArrayList占用的空间也是不小的,因为扩容的原因会浪费将近原来数组一半的容量,不过,因为ArrayList的数组变量是用transient关键字修饰的,如果集合本身需要做序列化操作的话,ArrayList这部分多余的空间不会被序列化。"
- Java的synchronized和Lock的区别 都是Java中用去解决线程安全问题的工具,是Java实现线程同步的方式。
- 身份:synchronized是Java内置关键字;Lock是个Java提供的一个接口;
- 释放角色:synchronized锁的释放是由JVM来决定的(异常或者运行完成);Lock可由开发者手动释放(建议释放锁放在finally,确保一定被释放)
- 锁粒度:synchronized锁住的是对象,而Lock锁住的是代码块。即synchronized只允许同一时间有且只有一个线程访问被修饰的方法或代码块;Lock可以针对不同的代码块分别加锁,允许多线程同时访问不同的代码块。
- 公平锁:synchronized不支持公平锁,Lock支持公平锁。公平锁意味着等待时间最长的线程获得锁,避免"饥饿"问题的出现。
- 等待中断:synchronized修饰的方法或者代码块是不允许被中断的;Lock接口则提供了中断等待锁线程的方法,如newCondition()方法
- Java的sleep和wait的区别
- 调用形式:sleep是Thread类的静态方法,可以任何线程中直接调用;wait是Object类的方法,需要对象内部通过引用调用。
- 锁释放:sleep方法不会释放对象的锁,而wait方法会释放对象的锁。即当某个线程调用sleep方法,它不会释放对象锁,其他线程仍然无法访问该对象;而当一个线程调用wait方法时,它会释放对象锁,其他线程可以访问该对象。
- 唤醒机制:sleep方法会使线程进入阻塞状态,需要指定的时间后自动唤醒。而wait方法会使线程进入阻塞状态,需要其他线程通过调用该对象的notify()或notifyAll()方法来唤醒。 参考博客:https://blog.csdn.net/qq_39890679/article/details/123923007
- Java的垃圾回收机制(GC)
- 概念:一种自动的内存管理技术,它负责回收程序中不再使用的对象所占用的内存。
- 作用:自动处理不再使用的对象的内存释放问题,从而减轻了程序员手动管理内存的负担;同时还可以提高程序的性能和稳定性,避免出现内存泄漏和野指针等问题。 ps:"垃圾回收机制如何判断对象是长期未使用的?"
- 引用计数:这是一种简单但效率较低的方法。当一个对象被引用时,它的计数器加一;当一个对象不再被引用时,它的计数器减一。
- 引用类型:通过引用类型判断,如果是强引用类型,GC是永远不会回收;如果是弱引用,只要一个对象没有被强引用指向,GC就可以随时回收这个对象;如果是软引用,只有在内存不足时才会被垃圾回收器回收。
- redis缓存穿透、缓存雪崩、缓存击穿的概念以及解决方案
- 缓存穿透:指查询数据库不存在的数据,同时缓存中也没有。因此每次请求都会绕开缓存,直接查询数据库。常见情况:黑客攻击,请求根本不存在的数据,不断攻击数据库,从而减低服务性能。
- 增加id复杂度,避免被猜测到id规律。
- 做好数据基础格式校验。
- 加强用户权限校验。
- 做好热点参数的限流。
- 缓存雪崩:指缓存层中存储的数据(key)大面积的一起过期失效,同时有大面积的请求访问这个失效的数据。
- 使用Redis集群部署方式,即使个别Redis节点下线,整个缓存层依然可以使用。
- 优化缓存过期时间设计,避免大量的 key 在同一时刻同时失效。(当时只答了这一点)
- 使用互斥锁控制,如根据 key 去缓存层查询数据,当缓存层为命中时,对 key 加锁,然后从存储层查询数据,将数据写入缓存层,最后释放锁。
- 缓存击穿:指一个被频繁访问(高并发访问并且缓存重建业务较复杂)的缓存键(热点key)因为过期失效,同时又有大量并发请求访问,导致请求直接落到数据库或后端服务上,增加了系统的负载并可能导致系统崩溃。
- 使用互斥锁,确保只有一个线程在访问缓存内容,并且在缓存中没有命中时,只会读取一次后端数据库(或其他数据源),其余线程会等待读取完毕后再次读取缓存。
- 使用逻辑过期,可以减少缓存的更新次数,避免在没有必要的情况下过多地读取后端数据源,并且在数据本身有频繁更新的情况下可以避免缓存数据过时
- redis的内存回收机制
- 定时删除:对于每一个设置了过期时间的Key,Redis都会创建一个定时器。一旦到达过期时间,定时器就会立即删除这个Key。这种策略可以立即清除过期的数据,对内存较友好。然而,它也会占用大量的CPU资源去处理过期的数据,会影响Redis的吞吐量和响应时间。
- 惰性删除:当客户端进行某个Key的get访问时,如果该Key被设置了过期时间并且此时get操作时Key已经过期,Redis将会针对该Key占用的空间进行回收。这种策略能最大限度地节省CPU资源,但是对内存却十分不友好。在一种极端的情况下,可能出现大量的过期Key没有被再次访问,因此不会被清除,导致占用了大量的内存。
- redis的持久化
- RDB:Redis会在某个时间间隔内,将内存中的整个数据快照写入磁盘。优点是恢复速度相对快,但是可能会丢失最近一次快照以后更改的数据。
- AOF:Redis将每次写命令记录到磁盘中,当Redis重新启动时,会重新执行AOF文件中的命令,从而将数据恢复到重新启动之前的状态。优点是持久化数据安全性高,并且易于备份,但是恢复速度相对较慢。
- 讲讲如何实现秒杀功能 这里我直接通过黑马点评的流程图来展示
通过lua脚本校验库存充足和用户重复下单,校验无误后,将订单ID和用户ID缓存到redis,后续通过异步线程将库存扣减写入到数据库MySQL中。 - redis实现分布式锁的方法
- SETNX命令:只有在键不存在时才设置值。可以用来实现分布式锁的加锁操作。
- 原子操作:Redis提供了原子操作来实现分布式锁的加锁和解锁操作。可以使用INCR命令来对一个键值进行自增操作;解锁时使用DECR命令对键值进行自减操作
- 分布式锁的实现框架:第三方框架如Redisson。
- MySQL和Mongodb如何实现数据共享 有点超过我个人现阶段水平了(捂脸) 这里放一个链接:MongoDB MySQL和MongoDB之间的数据同步|极客教程 (geek-docs.com)
- 上传代码平台,git的命令执行流程
- git init
- git add .
- git pull
- git commit -m "xxxx"
- git push
- Dockerfile的常用指令及作用 之前写了一份关于Docker学习笔记:极简版小白Docker学习篇(通俗易懂)-CSDN博

FROM centos # 最最基本的镜像基础
COPY target/xxxxx-0.0.1-SNAPSHOT.jar /app/xxxxx-0.0.1-SNAPSHOT.jar # 减少maven拉取jar包的时间 直接复制jar进入到容器的工作目录当中
ADD jdk-8u381-linux-x64.tar.gz /app/
WORKDIR /app
#5.配置环境变量
ENV JAVA_HOME=/app/jdk1.8.0_381 # 保持与上面添加的jdk版本一致
ENV CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH=$JAVA_HOME/bin:$PATH
EXPOSE 8081
CMD ["java", "-jar", "xxxxx-0.0.1-SNAPSHOT.jar","--spring.profiles.active=prod"]
- nginx的概念和功能
- 概念:高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。
- 功能:
- 反向代理:Nginx可以作为反向代理服务器,接受客户端的请求并转发给后端的服务器(集群)。在这个过程中,Nginx扮演了一个中介的角色,对外表现成一个服务器,但实际上它只是将请求转发给后端的真实服务器。这种设计可以减轻服务器的压力,提高数据的吞吐量。
- 负载均衡:当有高并发请求时,Nginx可以用来实现负载均衡。它有多种策略来实现负载均衡,例如轮询、权重、IP哈希等。通过这些策略,Nginx可以将数据流量分散到多个服务器上,提高系统的吞吐量和响应速度。 ps:这一部分的内容我不是很清楚详细内容(只写了我常听到的),还请球友指点!
- mybatis-plus的#和$符号的区别 他俩都实现动态SQL的方式
- 身份:#是占位符,等同于JDBC中的?;$是拼接符(动态参数),Mybatis不会对它进行特殊处理
-- #解析前
select * from user order by #{age} desc;
-- #解析后
select * from user order by ? desc;
-- $解析前
select * form user order by ${age} desc;
-- $解析后
select * from user order by age desc;
- 作用:#可以防止SQL注入;$常用于动态传参 PS:
- "SQL注入"是一种恶意用户采用SQL语句实现无账号登录,甚至操作数据库的网络攻击方式
- "动态SQL"可以根据不同的情景和需求动态的生成不同的SQL语句,提高更高的灵活性和可重用性。
- 2+2 和 2*2 在计算机的区别 主要体现于运算过程和运算规则,但都是用二进制进行计算。
- 运算过程:加法运算将两个数值相加,只需要考虑两个数位之间的进位;乘法运算则是将两个数相乘得到一个新的结果,普遍采用部分积左移和部分积右移的方法进行乘法运算。
- 运算规则:加法运算的规则是将两个数相加得到一个新的数;乘法运算的规则是将两个数相乘得到一个新的数。
- vue中路由守卫和路由导航的概念及其作用
- 路由守卫:一种用于控制用户访问特定路由的方法。它是一种可钩子函数,可以在路由被访问之前或之后执行一些逻辑。类似于ajax的请求拦截器,在请求发送之前先给拦截住做一些事情之后再去发送请求
- 全局前置首位
- 路由独享守卫
- 全局后置守卫
- 路由导航:是指通过编程方式或链接方式触发路由的跳转行为。
- 编程式导航
- 通过调用Vue Router实例的push、replace或redirect方法进行路由跳转。它们都接受一个路由参数对象作为参数,用于指定目标路由的路径、名称、查询参数等信息。
- 声明式导航
- 通过在模板中使用< router-link >组件进行路由跳转。< router-link >组件接受一个目标路由的名称或路径作为属性值,当用户点击该组件时,会自动触发路由跳转到对应的目标路由。
- 微服务和分布式的区别
- 概念:
- 分布式:是一种将系统划分为多个独立的业务模块,每个业务模块部署在不同的服务器上,通过接口进行数据交互的方式。
- 微服务:是一种架构风格,它将一个大的系统划分为多个独立的服务单元,每个服务单元负责特定的业务功能,通过接口与其他服务单元进行通信。
- 应用部署:
- 分布式:部署方式更加灵活,可以根据业务需求和系统规模进行灵活的配置。例如不同业务可以放在不同服务器也可以,也可以将统一的业务模块放在不同的服务器。
- 微服务:将每个服务单元部署在不同的服务器上,每个服务单元可以独立地进行开发、测试、部署和扩展。
- 介绍用户权限管理的框架(当时不清楚) 查了相关博客,目前常见主流的权限管理框架Shiro,适配于Java安全框架,提供了身份认证、授权、加密和会话管理等功能。
- 场景题
- 如果有500个囚犯,报单数会被枪毙,剩下顺势排序。依次往复,那么最后被枪毙的是什么号码(只提供思路) 思路:就是求得每个犯人号码整除2的次数,能够被2整除最多的就是存活最久的 假如有100名犯人,现在报数为奇数的枪毙,偶数的存活,请问,最后第几名犯人可以存活? - 爱热闹的杨小厨 - 博客园 (cnblogs.com)
- 每个海盗的分配顺序分别为1、2、3、4、5。抽到1号签的海盗,提出一个分配方案。对这种分配方案,5个海盗一起进行表决,如果海盗中有半数以上(含半数)的人赞成,那么它就获得通过,并以这一方案来分配100枚金币;假如他提出的方案被否决了,也就是只有半数以下的人赞成或没有人赞成他的方案,那么他将被扔进大海喂鲨鱼。这时就轮到2号签的海盗提出分配方案,然后剩余的4个海盗一起表决他的方案。和前面一样,只有超过半数(含半数)的海盗赞成,他提出的这一方案才能通过,并按他的这一方案分配100枚金币;反之,他和1号海盗一样会被扔进大海喂鲨鱼。同理,3号、4号海盗也是和上面一样的。当找到一个所有海盗都接受的分配方案时,这种情况才会结束。假如最后只剩下5号海盗,那么他显然是最高兴的,因为他将独吞全部金币。那么请问如何使得海盗利益最大化同时不被杀死?(PS:每个海盗都是很客观的!) 讲真,我当时挺想说平均每人20个金币(捂脸) 采用倒退的方式,来解决看似复杂的问题。海盗分金博弈-CSDN博客
- 其他(这个就不做回答啦~ 每个人情况都不太一样)
- 有接触什么新兴技术吗
- 大数据了解吗
- 元数据是什么
- 数据清洗
- python你平时用来干嘛
- 数学建模你会哪些算法
# 总结
还是有很多不足的地方。
- 基础不够扎实,回答层面太浅。如:只能回答是什么,如何用,但却不知道为什么要用。这让我得出一个结论,要学会对比学习,不能只停留在如何用,更要深入底层,多问自己"为什么是这样?"
- 学习的技术栈相对较少。问到一下技术或者概念,自己都是不太懂甚至没有听闻过,比如微服务的一些中间件(Kafka,RabbitMQ,ES等等)
- 车轱辘话太多,减少口水话。尽可能话要在点子上,不做过度的描述,准确精炼即可。
评论
问答助学
相关内容
0个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
内容推荐
我想问一下大家简历的字体是多少号的呢,是2页还是3页
2
今天面了两家公司,面试时间都比较短直接总结到一起了第一家1. 自我介绍2. 公司两个项目开发中,用到 Codex 或 Claude Code 了吗?3. 具体是用来写什么?用的是最多的哪个?4. Claude Code 用的是什么模型?5. 什么时候开始用的?(精确到具体月份)6. 是官方账号还是中转站?7. 当时开发一天用多少钱?8. 平时用到什么 Skill 或 MCP 吗?9. Claude
5
找实习从7月22号开始投,现在也总算是有offer了
5
怎么会有笨蛋从一月到现在,背了7个月的面试题,还啥都不会呢,到底背哪里去了,该怎么办
3
【入职求助贴】萌新刚入职某大厂做后端开发,目前还在试用期。最近遇到一个棘手的问题,想向大家求助一下。入职不久,leader 给我派了一个任务。跟我说是0.5天就可以解决,我刚毕业入职,做了一个星期没有做出来。实现一个收集定时成功任务的案例。听起来好像不复杂,但我自己摸索着做了一整个星期,到现在还没达到预期效果。这一周我基本是“边学边做”的状态,遇到卡点也会每天主动找 leader 沟通进度和疑问。
2

通过lua脚本校验库存充足和用户重复下单,校验无误后,将订单ID和用户ID缓存到redis,后续通过异步线程将库存扣减写入到数据库MySQL中。