首页 > 笔经面经 > 【社招-Java】阅文集团一面面经

【社招-Java】阅文集团一面面经

头像
李衿
编辑于 2020-07-17 16:12:52 APP内打开
赞 10 | 收藏 69 | 回复20 | 浏览5358

【社招-Java】阅文集团一面面经

个人履历:大厂一年 & 985本科

面试时长:70mins

面试轮次:一面(同事面)

面试形式:电话面试

面试过程:

  1. 个人履历简述

    略去不表

  2. 项目简述

    主要突出重难点,我bb了一堆业务逻辑结果人家都不感兴趣

  3. SpringAOP实现

    JDK动态代理:实现Invocationhandler接口,本质上是new一个继承了所有类上Interface的Proxy对象,然后通过method.invoke进行调用

    CGLib动态代理:在内存中动态生成子类对原对象进行代理,无法代理final类以及方法

    共同限制:无法代理到当前class当中this引用的嵌套方法

  4. AOP用的哪种?

    默认用的JDK动态代理

  5. JDK动态代理以及CGLib动态代理性能比较

    JDK走的反射,会多一些反射调用的开销(方法权限验证、调用开销等)

    CGLib需要创建新对象,在创建新对象上,即初始化时会多一些开销

  6. Java的线程池用过吗,具体参数讲一下

    Java的线程池是一个三级存储结构,线程先放入核心线程池,满了之后放到缓存队列当中,最后如果缓存队列也满了则扩容新线程

    所以参数有

    • 核心线程数量

    • 缓存队列类型

    • 最大线程数量

    • 线程活跃时间

    • 线程工厂方法(写日志、重命名线程等)

  7. 线程池的Execute和Submit区别

    Execute执行runnable,Submit可以执行Future,我们一般用countDownLatch+Future来获取所有的线程结果

  8. 继续问,还有别的区别吗?

    不知道了,后续查了发现区别如下

    Execute会在运行期直接抛出异常,Submit之后在调用Future.get的时候才会抛出异常

  9. 线程池如何保证当前线程获取池内的worker的时候不产生争用

    volatile的state标志这个worker有没有被使用

  10. volatile的特性

    通过禁止指令重排序来保证内存可见性,实际使用内存屏障实现的

  11. 内存屏障分几种?

    当时记不得了,回头查了一下如下

    LoadLoad屏障:对于这样的语句Load1; LoadLoad; Load2,在Load2及后续读取操作要读取的数据被访问前,保证Load1要读取的数据被读取完毕。

    StoreStore屏障:对于这样的语句Store1; StoreStore; Store2,在Store2及后续写入操作执行前,保证Store1的写入操作对其它处理器可见。

    LoadStore屏障:对于这样的语句Load1; LoadStore; Store2,在Store2及后续写入操作被刷出前,保证Load1要读取的数据被读取完毕。

    StoreLoad屏障:对于这样的语句Store1; StoreLoad; Load2,在Load2及后续所有读取操作执行前,保证Store1的写入对所有处理器可见。它的开销是四种屏障中最大的。在大多数处理器的实现中,这个屏障是个万能屏障,兼具其它三种内存屏障的功能。

  12. 除了在volatile当中使用了内存屏障,JAVA还有哪里使用了内存屏障

    这个真不知道,知道的小伙伴请在评论区指点一二

  13. 你之前讲到了CountDownLatch,你知道它的内部实现吗

    知道,用的AQS,在state=0的时候才允许所有等待的线程全部通过

  14. 简单讲一下AQS

    AQS核心设计:

    1. 一个volatile int state的状态值,使用volatile保证线程可见性,使用int来提供可重入的多资源能力

    2. 双向队列,首节点为执行节点,可以根据执行节点的Node信息判断是ShareLock还是ExclusiveLock,会关联一个执行线程,来提供可重入的判断

    3. 加锁的时候若是公平锁则尝试CAS再入队列,若是非公平锁则直接入队列

    4. 解锁的时候直接唤醒后继的第一个wait节点

  15. 加锁之后AQS是如何响应中断的

    太细节了真不会,源码没看这么深

  16. OK问点别的,AQS存在什么实现呢

    用过的ReentranceLock、CountDownLatch

  17. 讲讲实现

    ReentranceLock通过判断线程是否相同进行冲入

    CountDownLatch在state为0的时候才让所有的await通过

  18. 听说过ReadWriteLock吗,你之前提到AQS当中只有一个State那你如何用一个State去支撑读写两种状态

    一个state是Int,可以分高位给Read,低位给Write,就当个String用了

  19. Int几个字节

    我居然回答了32个,应该是32位,8位一个byte,共计四个byte

  20. 你们用过缓存吗

    没有,但是用redis做了分布式锁

  21. 你说说下分布式锁怎么做的

    分布式锁也是一个锁,需要满足几个特性,1 可重入 2 可以识别加锁的身份防止ABA问题 3 考虑是否需要续约

    key是所需要加上的锁的业务资源唯一编码,value是当前线程的uuid,uuid存在threadLocal内

    加锁的时候用的jedis,先设一个过期时间,然后用ex,若不存在key则添加新key,若已经存在则直接失败

    解锁用的阿里云企业版的CAD(compareAndDelete),原子比较并解锁,本质是通过lua脚本进行的类似事务操作

  22. 除了redis还有什么可以做分布式锁

    Mysql、zookeeper等

  23. 如果让你用Mysql做分布式锁你怎么做

    新建一张表,主键为需要锁的锁key,col1为线程uuid,col2为ttl时间

    加锁的时候在一个事务中先取当前key的record,若存在则判断ttl,若不存在则直接可以插入

    解锁的时候直接把record删除即可

    起一个定时任务来遍历表,清楚过期键防止无限膨胀

  24. zookeeper了解吗

    不了解

  25. 那我们继续聊聊Redis吧,Redis有什么数据结构?

    List,Hash,Set,Zset,List

  26. Zset怎么实现的

    跳表+map实现

  27. 什么是跳表

    常规链表只有一个next节点,跳表持有多个指向其他链表的指针,可以跨越式的进行查找,时间复杂度是logn

  28. 如果我要找一个score为A的节点应该如何去找

    首先在map中找到对应的node排名,然后根据排名在skiplist中进行查找

  29. zrange是如何实现的

    这个没想到不应该,查了一下如下:

    ZRANGE key start stop [WITHSCORES],zrange 就是返回有序集 key 中,指定区间内的成员,而跳表中的元素最下面的一层是有序的(上面的几层就是跳表的索引),按照分数排序,我们只要找出 start 代表的元素,然后向前或者向后遍历 M 次拉出所有数据即可,而找出 start 代表的元素,其实就是在跳表中找一个元素的时间复杂度。跳表中每个节点每一层都会保存到下一个节点的跨度,在寻找过程中可以根据跨度和来求当前的排名,所以查找过程是 O(log(N) 过程,加上遍历 M 个元素,就是 O(log(N)+M),所以 redis 的 zrange 不会像 mysql 的 offset 有比较严重的性能问题。

  30. Redis持久化

    RDB:快照存储,可以选择是否阻塞,使用场景在数据库上下线、主备复制等情况中

    AOF:类似于binlog,每个里面都是一个写事件,是优先读取的策略,支持多策略写入(强同步、按时间刷盘、交由操作系统决定刷盘等),AOF为了防止文件膨胀也支持重写

  31. AOF重写的时候会不会block主线程?

    不会,没有这个必要,起一个子线程重写完毕之后把手头的buffer在刷进去就行了

  32. 在载入的时候是怎么做的

    本地起一个client直接读取AOF重放其中的命令

  33. Redis有哪些多机部署方案

    经典的主备同步,通过RDB初始化备库然后进行命令传播

    Sentinel,实际上是一种容灾机制

    cluster,集群部署,使用多机占用slot的方式进行集群服务提供

  34. 在主备环境下,如果一个备库中途断链了,重新上线的时候怎么执行同步

    主备各自维护一个写入的Offset,对比差异之后在buffer中读出丢失的命令并进行同步

  35. 如果备库的offset过于落后已经不在buffer当中了呢

    1. 直接RDB重新同步

    2. 使用AOF来查找对应offset的语句(这个是我猜的)

  36. cluster如何做的故障转移

    不知道,估计也是检测到客观下线然后paxos选主

  37. Mysql了解吗,里面有哪些锁

    类型分类:共享锁(S),独占锁(X),意向锁(与表锁互斥)

    粒度分类:行锁、表锁

  38. 行锁怎么实现的

    不知道,这个时候已经有点崩溃了,怎么这么多不知道nnd

  39. 讲一下事务隔离级别吧

    RU、RC、RR、Serializable

  40. 你们用的是哪个隔离级别

    mysql默认的是RR,我们改成RC了

  41. 在默认隔离级别下会产生幻读问题吗?

    会,这是幻读是RR的经典问题之一

  42. 描述一下幻读

    在T1里Select * From table where id = 1;若不存在该记录则insert id = 1的记录进去,但是在select完毕之后T2事务插入了id=1的record,此时后续insert执行失败,本质上来讲是当前的快照读不支持后续dml语句的执行

  43. MVCC机制了解吗

    了解,由undolog支撑的数据隔离机制,主要是为了提供更高的并发度

  44. 讲一下原理

    每一行record都存在两个隐藏行,一个是当前的事务id,一个是指向undolog的指针

    mvcc机制运行在rr和rc两个隔离级别下

    在每次生成ReadView的时候,会将当前的活跃事务ID维护在列表当中,如果访问的Record的ID比最小活跃事务的ID还要小说明之前已经提交了,可以直接读取,如果与最大事务ID还要大就证明该事务在这个快照时没提交,需要根据undolog去找对应的历史版本,如果在最大和最小之间,那么若其为活跃事务则找历史版本,若不是则直接读取

    在RC级别下,每次Select都生成新的ReadView,所以能看到不同事物间的提交

    在RR级别下,只在第一次Select的时候生成ReadView,所以会产生幻读,因为快照读和真实读的结果不一致

  45. 慢sql怎么处理

    捞慢sql日志先分析写的索引是不是有问题或者offset太大了,然后看expain

  46. 你关注explain的那些col?

    1. key:真实用到的索引

    2. possible_key:可能用的索引

    3. rows:扫描行数,越大越拉垮

    4. filter:过滤数据比例,这个col可以验证索引有效性

    5. extra:包含是否使用索引、sort是否时filesort等

  47. https了解吗

    client发一个随机数给server server发证书+随机数回来

    client拆证书找第三方验证证书有效性,取出公钥

    client拿公钥加密第三个随机数发server

    server私钥解密

  48. 线上机器cpu100%你怎么处理

    容器化时代,一定要top看下是不是st过高,存在超卖的可能性

    如果不是的话top看下那个进程有问题,然后看这个进程哪个线程吃了cpu

    jstack直接把线程dump出来然后找对应有问题的线程再分析

    也有可能是内存泄漏导致的频繁GC问题,可以拉GClog然后在jmap把heap dump出来看下

  49. 你们线上JVM一般调整什么参数

    XMX&XMS固定防止内存抖动

    堆空间调整:年轻代Age调整、年轻代eden:s0:s1比例调整

    收集器调整:大促前把CMS的预清理次数调低一些,CMS的清理阈值调高一些

  50. 反问:

    1. 什么团队

    2. 做什么业务的

个人反思:

  1. 简历过长,难以被面试官抓住重点

  2. 项目使用技术栈没有体现出来

  3. 涉及相关项目重难点表述不清

    分布式锁、多租户的分库分表以及中间件隔离方案、性能问题排查等

  4. 各类技术栈停留在使用层没用再继续进行深挖

  5. 语速太快了,70分钟的面试大大小小回答了50个问题,我感觉放慢点够我回答两轮了

  6. 反问可以问的问题:

    团队简介、后端和前端协作流程以及定位、技术积累、对岗位的期待、招人原因、技术栈、内部CICD方案等

更多模拟面试

20条回帖

回帖
加载中...
话题 回帖

相关热帖

笔经面经近期热帖

历年真题 真题热练榜 24小时
技术(软件)/信息技术类
查看全部

近期精华帖

热门推荐