一面

Java 基础

  1. 谈谈 Java 程序怎么实现跨平台兼容的?
  2. 比如现在有一个 windows 32 位环境下编译好的 Class 文件,放到 linux 64 位环境下,可以运行吗?
  3. Javac 编译以后形成了 Class 文件,这个过程大致是怎么样的?
  4. 字节码直接就能执行吗,跟机器码有什么区别?
  5. Java 进程跟线程的联系和区别?
  6. 线程有哪些状态呢?
  7. wait() 和 sleep() 在面对锁的时候表现有什么不同?

计算机网络

  1. 客户端想和服务器建立 TCP 连接,要进行什么操作?
  2. TCP 通信时,上层的应用对 TCP 收到的数据会怎么处理?

数据库

  1. 通常有哪些手段可以优化 MySQL 的查询效率呢?
  2. 说说联合索引失效条件?
  3. 怎么查看查询语句用到的索引呢?

算法题

考了两道算法,不知道是我第一题做快了还是本来就准备考两道题。代码平台是牛客网。

  1. 将二叉搜索树转换为有序双向链表。调试不方便,简单写完核心逻辑(中序遍历放入 List 中再按序修改指针即可),讲完思路就算过了。
  2. 一个纯数字字符串,判断其是否可以通过加分隔点表示一个有效的 IP 地址(比如 “1111” 串可以表示 “1.1.1.1” 的 IP 地址)。数据量不大,直接暴力 DFS + 回溯解决了,面试官让自己设置几个用例测试一下。

反问

二面

二面这个面试官有点恶趣味,会接着上一面的一些问题对我继续追问,之前没见过这套路。

Java 基础

聊了 Java 的 IO 模型,这个我只看过八股,没有实操经验,硬接实在接不住,问到后面还是被问住了,看得出来面试官希望测试出我到底了解多深。

  1. Java 有哪些 IO 模型?
    BIO NIO AIO。
  2. 详细聊聊 BIO 和 NIO 的区别?
    我讲了 BIO 对每个连接都要启动一个线程去管理,同一时间只能有一个连接关联的线程运行,而其他连接的 IO 任务就要阻塞,并且读写的对象是数据流。而 NIO 用单独一个线程,通过 Selector 轮询一个个连接,查看 Buffer 中是否有内容,并按数据块复制到 Channel 当中。
  3. 那么 NIO 一个个轮循连接,跟 BIO 一个个切换线程,好像也没啥区别嘛,为什么说 NIO 的效率更高呢?
    我答了 NIO 按块从 Buffer 中复制,按块复制会比按流一个个字节复制更高效。
  4. 其实操作系统也是有自己的 IO 缓冲区的,所以 BIO 也可以利用缓冲,除此之外还有什么因素吗?
    (其实面试官的提问已经很有引导性了,奈何当时太紧张,没有答出 NIO 节约了线程切换的开销,哪怕看到博客里没有提到这点,其实稍微结合一下自己所学应该要能想到的)

计网

  1. 面试官接着我一面的话头问,一面我被问到应用层怎么验证报文的完整性。我回答应用层本身可以通过一些字段验证,比如 Http 有 Content-Length 可以指明报文主体部分的长度。二面面试官继续追问,还有没有其他方式,比如发送的 HTTP 主体部分是个流,事先无法确定长度?
    答得不好,先想到,客户端直接主动关闭连接就可以了。面试官赞同,追问其他方法?
    答不上来了,事后稍微总结了一下,其实还有一种方法是 chunked,也就是分块编码,最后一块长度与其他块不同,携带的附加信息也不同,可以表示报文传输完毕,详见我的计网面经整理
  2. TCP 哪些机制保证报文可靠送达?
    展开讲了 TCP 流量控制、拥塞控制、快重传等等机制。
  3. TCP 长时间收不到对方回应会怎么样?
    讲了 TCP 的 keep-alive 机制,每经过倍增的时间间隔发送一次探测报文,达到限定次数以后还没有反应就会关闭连接。
  4. 为什么 TCP 有了 keep-alive 了,应用层还需要设计各种心跳检测机制呢?
    因为 TCP 达到默认探测上限次数一共需要 2 个多小时,正常业务肯定是无法接受的,因此需要根据自己的需要来设计心跳检测。

算法题

一个单链表,反转第 m 到第 n 个结点,需要跑通牛客的测试用例。链表题本身想出思路没什么难度,主要是实现细节和调试上需要细心 + 耐心,不然跑不通用例的时候一紧张就很容易崩。

三面 + HR 面

猿辅导技术三面结束后连着HR面,跟三面是否通过没有关系。三面与 HR 面各自约 45 min,加起来一个半小时。