2022-05-14 07:31:41
以下是拼多多暑期后端一面的问题及解答:
自我介绍
需简洁说明教育背景、技术栈、项目经历及与岗位匹配的技能,突出后端开发相关的经验(如Java、数据库优化、分布式系统等)。
可以实习多久?将来工作去哪些城市工作有考虑过吗?
实习时长:根据个人情况明确回答(如3-6个月),需保证与学业无冲突。
城市选择:优先回答公司所在地(如上海、杭州等),或说明接受灵活安排。
Java的线程池有哪些核心参数?
核心线程数(corePoolSize):线程池中始终存活的线程数。
最大线程数(maximumPoolSize):线程池允许的最大线程数。
空闲线程存活时间(keepAliveTime):非核心线程空闲时的存活时间。
时间单位(unit):存活时间的单位(如秒、分钟)。
任务队列(workQueue):用于存放待执行任务的阻塞队列。
线程工厂(threadFactory):创建线程的工厂类。
拒绝策略(handler):当队列和线程池满时的任务处理策略(如AbortPolicy、CallerRunsPolicy)。
创建线程的时候,什么情况下会创建新线程?线程池是先创建线程,还是先进入队列?
创建新线程的条件:
当前线程数小于核心线程数时,直接创建新线程。
当前线程数大于等于核心线程数时,任务进入队列等待。
若队列已满且线程数小于最大线程数,则创建新线程。
执行顺序:
核心线程数未满时,优先创建线程。
核心线程数满后,任务进入队列。
队列满后,若线程数未达最大值,则创建新线程。
假设在线程池执行任务时,任务抛出了异常,线程会退出吗?所有异常都会导致线程退出吗?
线程是否退出:
任务抛出异常时,线程会终止,但线程池会重新创建一个新线程(若未达到最大线程数)。
异常类型影响:
非受检异常(如NullPointerException)会导致线程终止。
受检异常(如IOException)若未被捕获,同样会导致线程终止。
若任务中捕获异常并处理,线程不会退出。
如果线程池嵌套线程池,可能会有什么问题?
资源竞争:嵌套线程池可能导致线程数激增,超出系统资源限制。
任务堆积:子线程池队列满时,任务可能阻塞或被拒绝。
调试困难:嵌套结构增加线程管理和异常追踪的复杂性。
性能下降:频繁创建销毁线程导致上下文切换开销增大。
Java的List、Set和Map的区别?分别适用哪些场景?
List:有序、可重复集合,支持索引访问。
适用场景:需要按插入顺序遍历或通过索引操作的数据(如日志列表)。
Set:无序、不可重复集合,基于哈希或树实现。
适用场景:需要去重或快速查找的场景(如黑名单过滤)。
Map:键值对集合,键唯一。
适用场景:需要通过键快速访问值的场景(如缓存、字典)。
Map的Key可以为null吗?
HashMap:允许一个null键。
TreeMap:不允许null键(因依赖比较器)。
ConcurrentHashMap:JDK 1.7不允许null键,JDK 1.8允许但不建议使用。
在遍历List时,可以同时对List进行修改么?
直接修改会抛出ConcurrentModificationException。
安全修改方式:
使用迭代器的remove()方法。
通过CopyOnWriteArrayList实现并发遍历和修改。
遍历前复制列表,操作副本。
假设一个对象有两个属性,多线程同时修改时如何保证原子性(要么同时修改成功,要么都不成功)?
同步锁:使用synchronized或ReentrantLock保证代码块原子性。
原子类:对属性使用AtomicReference或AtomicInteger等。
CAS操作:通过compareAndSet实现无锁原子更新。
事务管理:在数据库层面使用事务(如Spring的@Transactional)。
如何实现跨域单点登录(如淘宝登录后访问天猫自动登录)?
共享Session:将用户信息存储在Redis等共享存储中,各子系统通过Token验证。
OAuth2.0协议:通过授权码模式获取访问令牌,子系统凭令牌访问用户资源。
JWT令牌:生成包含用户信息的加密令牌,子系统解析后自动登录。
MySQL的最左前缀匹配原则是什么?联合索引字段顺序调换还能生效吗?
最左前缀原则:联合索引(A,B,C)的查询条件必须包含最左字段A,才能利用索引。
字段顺序影响:若调换顺序(如B,A),则无法使用原索引,除非查询条件包含B和A。
索引中能不能有NULL?NULL值与其他值比较会怎样?
允许NULL:B+树索引的叶子节点可存储NULL值。
比较结果:NULL与任何值比较(包括自身)均返回未知(UNKNOWN),需用IS NULL或IS NOT NULL判断。
分库分表场景下如何生成全局唯一主键?
UUID:全局唯一但无序,不适合作为索引。
雪花算法(Snowflake):结合时间戳、机器ID和序列号生成有序ID。
数据库自增序列:通过AUTO_INCREMENT和LAST_INSERT_ID()实现跨库同步。
Redis原子操作:使用INCR命令生成递增ID。
怎么保证雪花算法的唯一性?还有别的分布式ID生成方案吗?
雪花算法唯一性:依赖时间戳、机器ID和序列号的组合,需确保机器ID不重复且时钟回拨处理。
其他方案:
Leaf:美团开源的ID生成服务,支持号段模式和雪花算法。
UidGenerator:百度开源的基于雪花算法的实现,支持自定义工作机器ID。
Redis Cluster的槽位(slot)机制是什么?如何固定某个key映射到固定槽?
槽位机制:Redis Cluster将16384个槽位分配给各节点,key通过CRC16算法计算槽位号。
固定映射:使用哈希标签({user1000}.profile)强制key分配到同一槽位。
Redis的pipeline是做什么用的?Pipeline是原子性的吗?
作用:将多个命令批量发送,减少网络往返时间(RTT),提升吞吐量。
原子性:Pipeline仅批量执行命令,不保证原子性。需用事务(MULTI/EXEC)或Lua脚本实现原子操作。
如何用Redis实现分布式锁?
SETNX命令:SET key value NX PX milliseconds实现锁的获取和过期时间设置。
释放锁:通过Lua脚本确保仅锁的持有者能释放(比较value后删除key)。
Redlock算法:在多个Redis节点上获取锁,提高可靠性。
Redis如何防止数据倾斜?大Key拆分具体怎么操作?
防止数据倾斜:
均匀分配哈希槽位。
避免热点key(如加随机后缀)。
大Key拆分:
将Hash/List拆分为多个小结构(如user:1:profile拆为user:1:profile:basic和user:1:profile:detail)。
使用分片存储(如按时间范围拆分)。
有没有用过Elasticsearch?
需根据实际经验回答,示例:
用于日志分析或全文检索,支持分词查询和聚合操作。
核心概念:索引(Index)、类型(Type)、文档(Document)、分片(Shard)。
什么是工厂模式?工厂模式和策略模式有什么区别?
工厂模式:通过工厂类创建对象,隐藏具体实现(如SimpleFactory、Factory Method)。
策略模式:定义算法族并封装,使它们可互相替换(如排序策略)。
区别:工厂模式关注对象创建,策略模式关注行为封装。
高并发系统如何做限流?
计数器算法:固定时间窗口内限制请求数(如Guava RateLimiter)。
漏桶算法:以固定速率处理请求,平滑突发流量。
令牌桶算法:允许一定突发流量(如Redis+Lua实现)。
秒杀系统如何防止超卖?
数据库乐观锁:通过版本号控制(UPDATE stock SET count=count-1 WHERE id=1 AND count>0)。
Redis原子操作:使用DECR命令扣减库存,若结果小于0则拒绝请求。
消息队列削峰:将请求写入队列,后台异步处理。
秒杀订单创建后未支付怎么处理?
超时关闭:通过定时任务扫描未支付订单,释放库存并标记状态。
延迟队列:使用RocketMQ或Redis实现延迟消息,触发关闭逻辑。
手撕:背包问题变种
问题描述:给定数组(物品重量)、背包容量(物品数量c和总重量h),求最小遍历次数。
思考方向:
动态规划:定义状态dp[i][j][k]表示前i个物品中选j个、总重k时的最小次数。
贪心算法:优先选择重量大且数量少的物品(需验证正确性)。
回溯法:模拟遍历过程,剪枝优化(面试官强调考察思考过程,无需完整代码)。