Java 面试时,你被深挖过什么问题?

本文由 简悦 SimpRead 转码, 原文地址 www.zhihu.com https://pic2.zhimg.com/v2-54bd6fad623816dca1774479b60514c6_xs.jpg?source=1940ef5c呵呵​

硕二 Java 后端开发,最近准备换工作,各大厂基本面了个遍,收获了阿里,美团,京东,快手,头条的 offer,总结了一下我面试各个大厂时候的面试题。

京东

一面:

  1. java 中的锁都有哪些?乐观锁和悲观锁,独占锁和共享锁,重入锁和非可重入锁,公平锁和非公平锁, 轻量级锁和重量级锁。附上自己总结的答案 呵呵:Java 并发之 Java 中的锁
  2. jvm 对锁的优化?锁升级,锁粗话,锁消除的概念。偏向锁 -> 轻量级锁 -> 重量级锁的过程。
  3. 工作中 volatile 的使用,volatile 的作用是?主要用于 DCL 单例模式中,volatile 的作用是禁止指令重排以及保证线程之间的可见性,底层主要是通过 cpu 的 lock 指令,锁住一个对 esp 寄存器加 0 的空操作,实现了内存屏障。
  4. 线程的创建方式?继承 Thread,实现 Runnable 和 Callable,或者使用线程池
  5. 线程池的核心参数以及工作机制?标准八股文
  6. 拒绝策略都有哪些?标准八股文
  7. NIO 和 BIO 的区别?非阻塞 IO 主要是通过操作系统提供的 api,创建 socket 的时候绑定 NON_BLOCK 属性,在执行 read、accept 等操作时,线程不阻塞,一直返回 - 1。一般可以结合多路复用器 select,poll,epoll 等使用。
  8. select,poll,epoll 有什么区别吗?select 主要将一堆文件描述符传到 select 的参数中,然后返回有时间就绪的文件描述符的个数,但是还是需要用户线程去主动轮训有哪些文件描述符有事件产生,缺点一是需要将文件描述符从用户态内核态之间拷贝,二是需要用户线程主动轮训文件描述符。epoll 是基于事件的回调的,可以通知用户线程那个文件描述符有事件就绪, 用户线程就不需要遍历了。
  9. 看过操作系统对 epoll 的实现吗?没看过。
  10. 讲讲 Netty。Netty 怎么用的?项目中用到过 netty,讲了讲。
  11. Netty 中怎么解决粘包问题的?内置一堆 handler,可以换行,可以根据分隔符,也可以根据传输的字节长度,http 就是会传输一个 content-length。
  12. Mysql 用过吗?项目中没用过 mysql,用的是 hbase,了解过 mysql。
  13. Mysql 的索引是什么数据结构,为什么用这种结构?标准八股文
  14. Redis 用过吗?常见数据结构,SDS 怎么实现的?SDS 是一个结构体,里面包含了一个 char 数组,一个 free 字段,一个 length 字段,获取字符串长度是 O(1) 复杂度,C 语言需要从头到尾遍历,复杂度高,另外还有二进制安全,惰性释放,避免缓冲区溢出等有点。
  15. Redis 的部署模式?单机,集群,哨兵等
  16. Redis 主从复制过程?当时不知道。 算法题 链表按 k 个一组反转。

二面:

由于一面问的基础知识很多,二面主要问问项目。包括项目中的流量走向,微服务拆分,项目 qps,考察对项目的了解程度。由于项目因人而异,不用说太多。

另外看我简历上有写大数据相关技术栈,考察了一个 HQL 的题。具体想不起来了。

算法题:

冒泡排序。由于太长时间没写冒泡排序了,给写成了选择排序。。。

美团

一面:

上来说项目,把项目中的各种问题,各种难点讲了讲。也是比较关注对项目的整体了解,以及对项目中各项指标的了解等。对 Java 基础方面没怎么问。除了项目方面的问题,主要有以下几个问题:

  1. Redis 主从同步的过程。由于之前在京东就被问过,当时不会回去看书了,这次就回答上了 ^ - ^。
  2. 为什么选用 Hbase,Hbase 和 Mysql 的区别是什么?怎样做技术选型?
  3. Hbase 调用一次的耗时是多少?
  4. Hbase 索引的原理。
  5. 介绍一下消息队列。Kafka 怎样保证高性能 IO 的。顺序写磁盘,零拷贝,批量处理减少 IO 次数等。

算法题:

记不清了,印象中不是很难。

二面:

依旧是说项目,项目对他们来说不是很难。

项目中遇到过什么问题?

项目中用到了 Netty,怎么用的,为什么用?

Netty 的事件循环是怎么回事?

Netty 的线程模型讲一下?Reactor 模型。

算法题:

将阿拉伯数字转为大写的汉语数字。注意处理零值,以及三千七百这种。

写算法题的时候看我写的代码还问到了 Switch 和 if 的那个性能高一些?Switch 有点像数组,if 需要不断的从头往后遍历,但是 if 有一些优化,如分支预测等。

三面:

前两面都通过了,三面就随便问了一下,基本没问技术的问题,最后出了个算法题。

  1. 你们做需求怎么做,需求评审怎么做?
  2. 目前几点上班几点下班?
  3. 平时团建怎么搞的?多久一次?
  4. 平时看书吗?最近看了什么书?

算法题:

旋转有序数组中找到某个值?二分查找。

阿里

一面:

  1. 项目中的容错限流,降级,兜底等怎么做的?
  2. 如果服务端挂了怎么,怎么降级?多级缓存,客户端内部缓存,CDN 缓存。
  3. 我们项目中是千人一面的兜底,那如何能做到千人千面?
  4. Mysql 异地多活该怎么做?有什么思路?
  5. 消息队列使用。场景题。
  6. Netty 介绍一下,项目中怎么用的。
  7. 项目中 Rpc 用的 thrift?thrift 用的什么序列化协议?为什么用这个协议?
  8. redis 主从同步?全量同步和增量同步。
  9. 超大文件排序应该怎么排?
  10. 数据库异地多活解决方案?附上答案 https://zhuanlan.zhihu.com/p/32009822

二面:

全程讲项目,项目中的各种细节,扣的很细,没问任何八股文。

三面:

三面是个 p10 大佬,也是问了问项目,说我项目比较薄(在大佬眼里当然薄了 _),然后又问了问我 offer 的情况和其他家薪资情况,其余的没细问。

头条

一面:

讲项目,除了项目还有下面的问题:

  1. redis 单机能抗多少 qps?
  2. redis 怎么避免热点 key 的?
  3. redis 中的常见的数据结构?介绍一下 SDS?
  4. 介绍一下跳表数据结构。查询的复杂度?新插入一个节点的流程。
  5. 为什用 Hbase 不用 Mysql,Hbase 的优势在哪?
  6. HBase 的索引以及 Mysql 的索引有什么区别?
  7. Java 中的 HashMap 实现原理以及 ConcurrentHashMap 实现原理?
  8. CAS 概念,有什么缺点怎么解决?
  9. 项目中有过哪些措施避免 Hbase 热点 Key?
  10. 解决过什么线上问题?

算法题:

给一个数组和一个数,找出数组中按照该数的全排列。

如数组 [1,2,3,4,5],给定的数字是 3,输出 [1,2,3],[1,2,4],[1,2,5],[2,3,4],[2,3,5],[3,4,5]

二面:

上来先讲项目,对项目中的问题扩展一下问一问。其余的问题如下:

  1. 微服务拆分的原则?为啥要拆分微服务?都放在一起有什么弊端?
  2. 讲讲项目中的流量走向?从 DNS->LVS->Nginx-> 网关服务 -> 聚合服务 -> 基础服务
  3. 讲讲 DNS 的流程?DNS 和 CDN 有什么联系?
  4. Mysql 分库分表的场景?什么时候需要分库分表?
  5. Mysql 设计题?项目中很少用到 mysql,没回答上。
  6. Java 中的多线程相关的东西。线程池?项目中的线程池用哪个?为什么不用 JDK 提供的静态方法中的线程池?
  7. 如果在主线程中创建了三个线程执行任务,想等三个任务都执行完了主线程继续执行,怎么实现?CountDownLatch。
  8. 手写 DCL 单例模式,为什么用 volatile?

算法题:

数组跳跃到最后需要的最少步。

三面:

讲讲项目,项目没问太细。其余的问题:

  1. java 中的 == 和 equals 的异同点,为什么经常需要同时实现 equals 方法和 hashCode 方法?
  2. java 中方法调用时传值还是传引用?
  3. 常见的设计模式?项目中用到过的以及源码中看到过的。

智力题:

四辆小车,每辆小车加满油可以走一公里,小车之间可以将油给其他的车辆,问如何能让其中的一台车走的最远?最远多少?

算法题:

0-1 背包问题。

快手

一面:

讲项目,对项目没问太细,只是大概聊了聊。

  1. 项目中有用到过的应对高并发的措施?消息队列,读写分离,冷热分离,缓存,避免热点 key 等。
  2. IO 方面?同步阻塞,同步非阻塞,异步非阻塞的概念。
  3. 有没有异步阻塞 IO?
  4. 讲讲 Netty,Netty 中怎么解决 TCP 粘包问题的?
  5. Redis 中的线程模型?为什么说 redis 是单线程的。
  6. Redis 的特点?怎样保证高可用的?
  7. Redis 的持久化机制?
  8. Redis 的淘汰策略?
  9. 分布式锁怎么做的?为什么用到分布式锁?
  10. 消息队列如何保证消息不丢失?
  11. 消费消息的时候做没做幂等?怎样做的? 算法题: 用数组实现队列。

二面:

先问项目,然后从项目中他比较感兴趣的一个点展开。

  1. 你们项目中服务注册发现用的什么?用的 ZK。
  2. 为什么用 ZK,ZK 有什么特性?
  3. 服务发现的过程?
  4. Rpc 调用的时候路由规则是什么?有权重的随机路由。
  5. 在服务升级的时候,需要下线掉原来的服务,但是会有时间处于新的服务和旧的服务之间,请求可能会调用到新的代码也可能会调用老的代码,这个你们怎么处理的?

算法题:

实现一个阻塞队列

由于我看过 JDK 中 Doug Lea 写的源码?所以写的不怎么费劲,下面附上 JDK 中的给的例子。

注意里面的判断需要用 While 不能用 if,有一个虚假唤醒的机制,用 if 可能会有错。其实就是因为如果用 if 的话,if 里面的 notFull.await() 方法会释放掉锁,可能出现其他线程改了这个变量,导致条件不满足了,而用 while 的话会在继续判断这个条件。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class BoundedBuffer {
     final Lock lock = new ReentrantLock();
    final Condition notFull  = lock.newCondition(); 
    final Condition notEmpty = lock.newCondition(); 
 
    final Object[] items = new Object[100];
    int putptr, takeptr, count;
 
    public void put(Object x) throws InterruptedException {
      lock.lock();
      try {
        while (count == items.length)
          notFull.await();
        items[putptr] = x;
        if (++putptr == items.length) putptr = 0;
        ++count;
        notEmpty.signal();
      } finally {
        lock.unlock();
      }
    }
 
    public Object take() throws InterruptedException {
      lock.lock();
      try {
        while (count == 0)
          notEmpty.await();
        Object x = items[takeptr];
        if (++takeptr == items.length) takeptr = 0;
        --count;
        notFull.signal();
        return x;
        } finally {
        lock.unlock();
      }
    }
  }

三面:

三面依旧是上来就讲项目,然后问了问细节。后面主要问了一下下面的问题,从这个问题展开问了很多:

  1. 线上如果出现耗时长,怎么排查?有可能是什么原因?用 Arthas 来查,可以定位到具体某个方法调用的耗时。或者查日志,看每个日志的打印出来的时间,在去判断。一般耗时长可能都是有 IO 操作,可能访问数据库了。
  2. 怎么避免访问数据库带来的耗时严重呢?加缓存。
  3. 如果加了缓存还是耗时长可能什么原因呢?可能有缓存穿透的问题。
  4. 什么是缓存穿透?大量请求查缓存中的数据不存在,流量都直接打到了数据库上。
  5. 怎样解决缓存透?将请求数据库不存在的值在缓存中存储一个空值,下次请求同一个值的时候就直接访问缓存并且返回了,不会请求到数据库上。

算法题:

对称树的判断。

总结:

总体来说京东给我的面试体验最好,其次是阿里和美团,各个大厂的风格也比较不同,像阿里就完全问项目,几乎不问基础,考察你对项目的了解程度,细节扣的很深,算法也几乎不问,头条就算法题几乎必须做出来,不然基本不会过。

点赞,喜欢,收藏这三者任选其一就行,如果能给一个关注,那更是对我莫大的鼓励,感谢您的支持

https://pic1.zhimg.com/v2-88e2e1350c8d00d366fe3861b302029a_xs.jpg?source=1940ef5c狼王编程

没想到 POST 和 GET 请求的问题我被问了这么多,下面我以面试的方式来讲讲我的经历!

小伙伴们写过接口或者使用过网页开发者模式的,肯定对以下的内容不陌生

![](data:image/svg+xml;utf8,)![](data:image/svg+xml;utf8,)![](data:image/svg+xml;utf8,)

没错,这些就是HTTP请求的方式

有一次面试的时候也被问到了这个问题,下面我会以面试的形式呈现给大家, 那么就让我把大家拉到面试的现场吧!


持续的脚步声,由远及近,随之会议室的门被推开了,我起身定睛一看面试官,他那发际线即将触碰到后脑勺,大框黑边眼镜也掩盖不住那黝黑的眼圈,显得格外的程序员, 穿着也非常不拘一格,上半身是衬衣西服,下半身是牛仔裤配拖鞋。

https://pic1.zhimg.com/v2-fd92ab45d9d121d9a401e2e7511d43de_r.jpg?source=1940ef5c

我心中的默念: 真大佬,无疑了!

随后面试官就让我坐下,面试就正式拉开帷幕!


自我介绍以及其他问题此处省略 1w 字…

面试官:平时开发过程中,你们常用的HTTP请求方法都有哪些啊?

:是这样的,HTTP/1.1协议中共定义了八种方法,有时也叫动作,来表明Request-URL指定的资源不同的操作方式

  1. 在 HTTP1.0 中,定义了三种请求方法:GET, POST 和 HEAD方法。
  2. 在 HTTP1.1 中,新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT方法 但我们常用的一般就是GET和POST请求。

面试官:嗯,那你说说 GET 和 POST 请求都有哪些区别呢?(果然进套了,看你小子有几斤几两)

https://picx.zhimg.com/v2-80a3fccdbd11aeaf00eb3bf3dac20888_r.jpg?source=1940ef5c

:(我假装被难住,然后思考了一会儿说)这个。。。没有特别去关注过,但是按照我的理解,大概有这么几种区别吧:

  1. GET 请求在 URL 中传送的参数是有长度限制的,而 POST 没有。
  2. GET 比 POST 更不安全,因为参数直接暴露在 URL 上,所以不能用来传递敏感信息。而 POST 数据不会显示在 URL 中。是放在 Request body 中。
  3. 对参数的数据类型,GET 只接受 ASCII 字符,而 POST 没有限制。
  4. GET 请求参数会被完整保留在浏览器历史记录里;相反,POST 请求参数也不会被浏览器保留。
  5. GET 请求只能进行 url 编码( application/x-www-form-urlencoded),而 POST 支持多种编码方式。
  6. GET 请求会被浏览器主动缓存,而 POST 不会,除非手动设置。
  7. GET 在浏览器回退时是无害的,而 POST 会再次提交请求。

面试官心里:(没关注过,那你还背的一条不差。跟我搁这儿装杯呢?看我怎么教育你。)

https://pic3.zhimg.com/v2-8ce819fb161eaf6b32836a491ebee5bb_r.jpg?source=1940ef5c

面试官:那 Get 请求有 Request body 么?如果有的话参数可以像 Post 请求一样放在里面么?

:(吼吼,看来有机会把我昨天精心准备的东西给他扯半小时了 [手动挠头] 让开,我要开始放大招了)

![](data:image/svg+xml;utf8,)

其实吧,GET 和 POST 在本质上没有区别,都是 HTTP 协议中的两种发送请求的方法。而 HTTP 呢,是基于 TCP/IP 的关于数据如何在万维网中如何通信的协议。

万维网:简称 WWW,是 World Wide Web 的简称,也称为 Web、3W 等

HTTP 的底层是 TCP/IP。所以 GET 和 POST 的底层也是 TCP/IP,也就是说,GET/POST 都是 TCP 链接。

GET 和 POST 能做的事情是一样一样的。你要给 GET 加上 request body,给 POST 带上 url 参数,技术上是完全行的通的。

举个栗子吧:(嗯?栗子?好饿,待会儿面试完去买点)

https://pic3.zhimg.com/v2-5fb3c38dbf97d4ef27d8d8bc57b30e19_r.jpg?source=1940ef5c

TCP 就像汽车,我们用 TCP 来运输数据,它很可靠,从来不会发生丢件少件的现象。

但是如果路上跑的全是看起来一模一样的汽车,那这个世界看起来是一团混乱,送急件的汽车可能被前面满载货物的汽车拦堵在路上,整个交通系统一定会瘫痪

为了避免这种情况发生,交通规则HTTP诞生了。HTTP 给汽车运输设定了好几个服务类别,包括GET, POST, PUT等等,

HTTP 规定,当执行 GET 请求的时候,要给汽车贴上 GET 的标签(设置 method 为 GET),而且要求把传送的数据放在车顶上(url 中)以方便记录。

如果是 POST 请求,就要在车上贴上 POST 的标签,并把货物放在车厢里(request body 中)。

当然,你也可以在用 GET 的时往车厢内偷偷藏点货物,但这并不不光彩;也可以在 POST 的时候在车顶上也放一些数据,也会让人觉得傻乎乎的。

https://pic2.zhimg.com/v2-b6d67c6b686906503fddef882124736d_r.jpg?source=1940ef5c

HTTP 只是个行为准则,而 GET 和 POST 本质上就是 TCP 链接,并无差别。但是由于 HTTP 的规定和浏览器 / 服务器的限制,导致他们在应用过程中体现出一些不同。

面试官心里:(哎呀,这小子还真的了解这块儿啊,看来是我误会他了,难道遇到了大佬?)

https://pica.zhimg.com/v2-397a9816cde58d9379450003ac65dd90_r.jpg?source=1940ef5c

面试官:你说的不错,那你刚才说的 URL 中传送参数的长度限制在 Get 和 Post 中都是怎么样的呢?

:其实在 Web 中啊,还有另一个重要的角色:运输公司

不同的浏览器 Client 端(发起 http 请求)和服务器 server 端(接受 http 请求)就是不同的运输公司。

虽然理论上,你可以在车顶上无限的堆货物(url 中无限加参数)。但是运输公司可不傻,装货和卸货也是有很大成本的,他们会限制单次运输量来控制风险,数据量太大对浏览器和服务器都是很大负担

业界不成文的规定是,(大多数)浏览器通常都会限制 url 长度在2K个字节,而(大多数)服务器最多处理64K大小的 url。

超过的部分,恕不处理。如果你用 GET 服务,在 request body 偷偷藏了数据,不同服务器的处理方式也是不同的,有些服务器会帮你卸货,读出数据,有些服务器直接忽略。

https://pica.zhimg.com/v2-c2ee001d4b2950bd8f7823a5d47c882c_r.jpg?source=1940ef5c

所以,虽然 GET 可以带 request body,却不能保证一定能被接收到

面试官:(看来理论确实是掌握的不错,让我考考他实际应用)那 GET 方法参数写法是固定的吗?

:在约定中,我们的参数是写在?后面,用&分割。就像下面这样:

http://ip:port/test/getHelloWorld?username=langwang&age=26&sex=2

我们知道,解析报文的过程是通过获取 TCP 数据,用正则等工具从数据中获取 Header 和 Body,从而提取参数。

比如 header 请求头中添加token,来验证用户是否登录等权限问题。

也就是说,我们可以自己约定参数的写法,只要服务端能够解释出来就行,万变不离其宗。

面试官:那么说来,是不是 POST 方法比 GET 方法更安全呢?

:有人说 POST 比 GET 安全,因为数据在地址栏上不可见

然而,从传输的角度来说,他们都是不安全的,因为 HTTP 在网络上是明文传输的,只要在网络节点上捉包,就能完整地获取数据报文。

其实,要想安全传输,就只有加密,也就是 HTTPS

面试官:嗯,不错不错,看来你对 HTTP 协议这块儿还是有一定了解的,那么你知道 Get、Post 请求发送的数据包有什么不同吗?

:(看来这面试官是非要是把我问倒才满意啊?可惜可惜。看我套路他一波)

面试官,实不相瞒,我上家公司加班比较多,最近刚签完离职,贵公司是我面得第一家公司,所以准备的不充分,这样吧,我大致谈谈我的理解吧,不对的地方您见谅。

面试官:没关系,按你的理解聊聊就行。(这小子没准备就说成这样,我的好好考虑一下,别错失了先机,失去一个能为公司加班的人才)

:嗯嗯,是这样的,GET 请求时产生一个TCP 数据包;POST 请求时产生两个TCP 数据包。

  1. GET:浏览器会把 http header 和 data 一并发送出去,服务器响应 200(返回数据);
  2. POST:浏览器先发送 header,服务器响应 100 continue,浏览器再发送 data,服务器响应 200 OK(返回数据)。

就像是 GET 只需要汽车跑一趟就把货送到了,而 POST 得跑两趟,第一趟,先去和服务器打个招呼老铁,我等下要送一批货来,你们准备接收一下哈,然后再回头把货送过去。

因为 POST 需要两步,理论上时间上消耗的要多一点,看起来 GET 比 POST 更有效。但并不是,后来发现原来是个坑。在我看来:

  1. GET 与 POST 都有自己的语义,不能随便混用。
  2. 据研究,在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下,两次包的 TCP 在验证数据包完整性上,有非常大的优点。
  3. 并不是所有浏览器都会在 POST 中发送两次包,Firefox 就只发送一次。我去年用 Chrome 浏览器测试发现也是只发送一次,所以我认为 Get、POST 性能差可以人为忽略。

面试官:嗯,你说的很不错,那你稍微等一下啊。

:(难道还有变故?这波操作难道被发现了我在套路面试官?不应该啊)

五分钟后,面试官拿着一杯饮料走了进来。。。。

面试官:你尝尝这咖啡味道如何?(自古套路得人心,学好了)

我喝了一口,竖起大拇指说到:面试官,这是正宗的卡布奇诺啊,我平时就喜欢喝,可惜太贵了。。

咦?我进来之前没有看到你们这有咖啡店呀,这是?

面试官嘴角上翘,微微一笑,露出了洁白的两颗大门牙说到:

我看你简历说你爱喝咖啡,巧了,我们公司有专门的水吧,福利之一就是是每天免费一杯咖啡或饮料。以后你可以经常喝了。

:那您的意思是,我面试过了是么,太好了!对了水吧每天几点下班呐?跟开发一个点儿么?(不会是因为经常加班才免费喝咖啡吧,我得试探试探)

面试官:哈哈是啊,水吧一直都是按点下班,咱们公司如果有人加班的话,可以自己去水吧做着喝就行,加班时间都是免费的。你这儿没问题的话,我看下周一就入职吧。

:好的,面试官,我回去考虑下,到时候和您联系,再见!

至此,本次关于 HTTP 请求方式,以及 GET 和 POST 的区别相关的面试就结束啦,感谢大家的观看!


好了。今天就说到这了,我还会不断分享自己的所学所想,希望我们一起走在成功的道路上!

关注等于白嫖,点赞才是真情!

关注等于白嫖,点赞才是真情!

关注等于白嫖,点赞才是真情!

**觉得不错的点下关注和赞啦!**​狼王编程

https://pic3.zhimg.com/v2-262fc2f8b30a4925a9d9bea17b0c9bcd_xs.jpg?source=1940ef5c小傅哥​

![](data:image/svg+xml;utf8,)

哈,你竟然敢问面试的坑挖多深,仅 Java 基础来说:

  • HashCode 为什么用 31 作为乘数,你证明过吗?
  • 扰动函数的函数作用是什么,它还有什么场景在用?
  • 拉链寻址和开放寻址具体是什么表现,怎么解决的碰撞问题?
  • ThreadLocal 的实现中还有黄金分割点的使用,你知道吗?
  • CLH、MCS,都是怎么实现的公平锁,代码是什么样?
  • jvmti 可以用于非入侵的监控线程池状态,你用过吗?

关于以上的问题,是不有种即使看过 Java 核心 API 的源码,也很难回答出来?

这是因为 Java 代码本身就是基于数据结构和算法对数学逻辑的具体实现,而那些隐含在代码中的数学知识如果你不会,那么压根你就会忽略掉它,也就因此看不懂源码了。如果你感兴趣这也的技术广度和深度,也可以和我一起折腾,来吧!

https://github.com/fuzhengwei/CodeGuidehttps://pic3.zhimg.com/v2-932a96e7439d93f96278e8e1f207be45_r.jpg?source=1940ef5c

接下来分享个小伙伴面美团一面,求职方向是团队技术负责人。此次面试以连环追问的方式为主,喜欢刨根问底,非常考研面试者的技术功底。以下是整理出的部分面试题,我们看看这些题该如何回答。

美团现场面试

  1. 先让写个线程安全的单例模式
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public class Singleton {

    private static volatile Singleton instance;

    private Singleton() {
    }

    public static Singleton getInstance(){
       if(null != instance) return instance;
       synchronized (Singleton.class){
           if (null == instance){
               instance = new Singleton();
           }
       }
       return instance;
    }

}
  • 考察线程安全的单例模式,一方面是对基础的了解,另一方面以单例模式作为入口考察并发编程的知识点。
  • 在这里你要知道,并发编程的三要素包括:原子性、可见性、有序性。
  • 那具备三要素知识点的单例模式,主要是如上案例中的双重检查锁和 CAS 忙等策略。而双重检查锁的单例方式,对于面试官和求职者来说,可以往下继续聊的点就有了。
  • 当然,如果你没有写出这样一种单例模式,大概率会被面试官引导过来。在面试的过程中最好的方式是主动和引导面试官走,也称对脾气,也就是技术臭味相投的感觉。
  1. 高并发下,单例模式会存在哪些问题?
  • 单例模式就是以防止线程不安全和提高代码执行效率而设计的。
  • 双重锁定检查 (DCL,Double Check Lock),也就是为此设计的。别被 DCL 唬住喽
  1. 可见性和指令重排是怎么回事?
  • 可见性,Java 编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致地更新,线程应该确保通过排它锁单独获得这个变量。
  • 指令重排,在程序执行过程中为了性能考虑,,编译器和 CPU 可能会对指令重新排序。对于并发多线程场景下,指令重排会产生不确定的执行效果。
  1. voliate 关键字为什么可以解决可见性和指令重排?

可见性

  • 首选,volatile 关键字修饰的共享变量可以提供这种可见性规范,也叫做读写可见。
  • 被 volatile 关键字修饰的共享变量在转换成汇编语言时,会加上一个以 lock 为前缀的指令,当 CPU 发现这个指令时,立即将当前内核高速缓存行的数据回写到内存,同时使在其他内核里缓存了该内存地址的数据无效。
  • 另外,在早期的 CPU 中,是通过在总线加 LOCK# 锁的方式实现的,但这种方式开销较大。所以 Intel 开发了缓存一致性协议,也就是 MESI 协议,该解决缓存一致性。
  • volatile 的好处,volatile 是一种非锁机制,这种机制可以避免锁机制引起的线程上下文切换和调度问题。所以,volatile 的执行成本比 synchronized 更低。
  • volatile 的不足,volatile 关键字只能保证可见性,不能保证原子性操作。
  • 此外如果你还能回答出,Unsafe.loadFence(); 保证在这个屏障之前的所有读操作都已经完成。的一些使用,那么面试绝对可以加分。

指令重排

1
2
3
public volatile boolean sign;
    descriptor: Z
    flags: ACC_PUBLIC, ACC_VOLATILE
  • 从字节码层面,添加 ACC_VOLATILE,在汇编指令的打印会有 lock addl $0x0,(%rsp)s
  • 从 JVM 层面,JMM 提供了 8 个 Happen-Before 规则来约束数据之间竞争、4 个内存屏障 (LL LS SL SS) 和 As-if-serial
  • 从硬件层面,sfence、lfence、mfence
  1. 除了双重检查锁之外,还有什么别的办法实现线程安全的单例模式。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public enum Singleton {

    INSTANCE;
    public void test(){
        System.out.println("hi~");
    }

}

@Test
public void test() {
    Singleton_07.INSTANCE.test();
}
  • 如果再让写一种差异比较大,方式不太一样的单例模式,那么 Effective Java 作者推荐使用枚举的方式这个时候可以甩出来秀一波了。
  • 这种方式解决了最主要的;线程安全、自由串行化、单一实例。
  1. 你看过什么源码吗?JVM 的源码是否看过?
  • 看过 Dubbo、Spring、Mybatis 等框架和一些中间件的源码,关于 JVM 多线程、并发、锁等核心内容的源码有所了解。
  • 其实这块问你的内容,主要考察你对技术的学习是否有核心深度。如果你能对此有所回答,那么会得到面试官的一定认可。
  1. Dubbo是怎么工作的?
  • 简单来说,引入 Dubbo 服务的接口提供方与接口消费方,通过注册与拉取接口信息,把服务双方通过 Socket 进行连接。之后接口通信的时候通过代理类传输 Socket 请求,再由接口提供方通过反射调用真实服务,最终把接口执行信息返回给调用端。
  • 在整个的回答过程中,可能会聊到注册中心、代理、反射、通信模型以及 Netty 的相关知识,这主要包括了通信协议的定义、半包粘包以及流量整形和各类知识。
  1. Dubbo通信是用的什么协议?

https://pic2.zhimg.com/v2-06e13440f182d55cc1ecf64716ed6f88_r.jpg?source=1940ef5c

  • Dubbo 主要支持这些协议:dubbo://、rmi://、hessian://、http://、webservice://、thrift://
  • rmi 协议:走 java 二进制序列化,多个短连接,适合消费者和提供者数量差不多,适用于文件的传输,一般较少用
  • dubbo 协议: 默认就是走此协议,单一长连接,NIO 异步通信,基于 hessian 作为序列化协议
  • hessian 协议:走 hessian 序列化协议,多个短连接,适用于提供者数量比消费者数量还多,适用于文件的传输,一般较少用
  • http 协议:走 json 序列化
  • 此外序列化的方式还有 protobuf,protobuf 全称 Google Protocol Buffers,是 google 开发的一套用于数据存储,网络通信时用于协议编解码的工具库。

9 . 属于网络传输中的哪一层?

https://pic1.zhimg.com/v2-9aaaba919b354b794a1c2d3cf98c9154_r.jpg?source=1940ef5c

  • TCP/IP 四层模型,是 OSI 七层模型的简化,泛指众多 (TCP,UDP,IP 等) 协议。
  • Dubbo 协议是 TCP 协议之上的协议,采用单一长连接和 NIO 异步通讯。
  1. TCP/IP协议来说建立连接的时候,为什么需要三次握手?
  • 三次握手是在安全可靠的基础上最少握手次数的方案,而两次握手并不能保证可靠性,四次握手又浪费了传输效率。
  • TCP 传输控制协议,是一个面向连接的协议。在 TCP/IP 协议中,TCP 协议提供可靠的连接服务,连接是通过三次握手进行初始化的。对于这部分知识可以深入了解下,资料也很丰富。
  1. 你刚才说你们公司用的是Kafka,那么你觉得什么场景下要用到Kafka呢?

https://pic2.zhimg.com/v2-9993c4e4bbfebc568e2018120afa27fb_r.jpg?source=1940ef5c

  • 首先要知道,开源社区有很多优秀的队列中间件,比如 RabbitMQ、ActiveMQ、RocketMQ、Kafka,有些大厂还有自研的 MQ 队列中间件。
  • 解耦、消峰、驱动等场景下的业务时以及日志采集系统、监控系统、流式处理等各类场景中都离不开 MQ 队列。
  1. 你觉得对于一个消息中间件来说,需要达到哪些要求?
  • 高吞吐、低延时、可用性和可维护性,是消息队列中间件的核心要求。
  • 同时你可以说出,中间件的作用是解决共性凝练和复用,从本质上提升代码的复用性、松耦合和互操作的标准机制,从而提升研发整体交付效率。
  1. Kafka是如何做到高吞吐量的?
  • Kafka 是分布式消息系统,需要处理海量的消息,Kafka 的设计是把所有的消息都写入速度低容量大的硬盘,以此来换取更强的存储能力,但实际上,使用硬盘并没有带来过多的性能损失。主要围绕顺序读写、零拷贝、文件分段、批量发送和数据压缩几个方面提高吞吐率。
  1. 接下来是关于一些项目的问题
  • 在公司做过哪些项目,主要是哪方面?基础中间件还是业务项目?这个项目的主要难点在哪里?怎么解决的?
  • 项目做到现在,有没有一些数据上的评价指标,表示这个项目做得不错?如果没有,那么现在让你自己评价一下,你觉得应该从哪些方面做考量?
  • 对于一个系统来说,如何确保它的稳定性?(线程池用的哪种?为什么要用这几种?怎么用的?)
  • 你在项目当中扮演什么样的角色?系统 Owner 还是开发?
  • 你们团队的人员分布是怎么样的?内编几个,外包几个?如果带外包的话,如何管理外包?
  1. 面试复盘
  • 基础知识要牢固,JVM 内存分布,多线程,基本是面试必问的。其中多线程并发的源头:可见性,有序性,原子性相关的知识点一定要深入理解,能讲多清楚就讲多清楚,因为这些涉及到 CPU,内存,指令集等底层知识,是多线程理论的源头。这方面的东西,如果面试官本身具备一定实力的话,是很容易深究下去的,如果只是浅尝辄止,一知半解,很容易暴露自己底层知识的不牢。逼格就会降低一个大的档次。
  • 要有一定动手能力,一些常见的设计模式要随时随地可以写出来,如果有多种方案实现的话,需要都讲出来,并指出其中的优缺点。
  • 分布式理论要扎实,要深入理解常见 RPC 框架(如 dubbo)和消息队列的设计和实现原理。一个框架的出现,以及平时业务开发所遇不到的各种高阶知识点(比如 dubbo 的重试机制,熔断,降级服务等,kafka 相比 ActiveMQ 等其它消息队列,优势在哪里,为什么它可以支撑那么高的吞吐量等等),一定是为了解决某些特定问题才会出现的,了解了问题源头,才能更好理解框架的全局设计思想,然后才能更好地吸收框架里面的各种解决方案以及背后体现出来的思想。
  • 网络基础要夯实,http,https,TCP/IP 协议以及网络通信的基础知识还是要知道的。
  • 实际项目一定要学会总结,让人看到你做项目的亮点(代码规范,可维护性,可扩展性,稳定性,性能优化,访问量,以及一些其它的数据指标)。如果没有,一定要想办法自己加入一些可信的东西出来。毕竟面试官无法验证你说的是真是假,如果说得很像那么回事,面试官应该还是会认可的。

大厂地图

https://pic1.zhimg.com/v2-e944c6efef89f83b3a9245b828fd4bbf_r.jpg?source=1940ef5c

  • 从图上可以看到大部分互联网公司都分布在北边, 让人怪不好意思的,集中在一块挺好,下楼吃个饭就跳槽了。
  • 就我自己而言更喜欢靠边一点的公司,因为租房便宜、不用挤地铁、不用把时间浪费在路上、不用听马路的嘈杂。

什么样能进入大厂

1. 你的简历

可能很大一部分1~3年找工作的小伙伴,只是按照模板填写好简历就完事了,很少考虑公司都需要什么、自己的职位是否匹配。

但你可能忽略了,你的这份简历才更多的决定了你会遇到一个什么样的公司、什么样的面试官、什么样的考题。最终决定你与这家公司的匹配的程度。

在与很多小伙伴沟通中发现,其实很大一部分程序员都不会写简历的,或者说写不好简历。好像是有话说不出来,或者是不知道该把这些话说在哪。一份简历主要得体现出你个人的信息、技术栈广度和深度、项目经验以及最后一块拓展内容。

而这份简历想达到最终的效果,也就是拿 Offer。那么一定要给面试官挖坑,当然这个坑不是真坑。而是你要在简历中突出自己的优势项、技术亮点、优秀经历,也同时在这些点中留出技术话题,让面试官可以和你有的

但如果说你胡乱写简历,说自己懂 HashMap。那面试官来劲了,问你:Hash为什么用31计算扰动函数的作用是什么,以及它可以被应用在哪些地方负载因子嘎哈的HashMap是开放寻址还是拉链寻址链表什么时候树化以及迁移数据算法是什么2-3树和红黑树有什么关系等等,你不晕才怪,也不能给面试官留下好印象。

Java 面经手册 · 小傅哥. pdf_小傅哥 - 互联网其他资源 - CSDN 下载

2. 大厂考题

以下这部分考题分析数据是通过抽样的方式,从 Boss 直聘中选取六个互联公司,每个公司找 35 个,工作 13 年岗位应聘要求,从中分析各面试考点综合汇总。

样例数据

2.1 阿里、百度、腾讯

https://pica.zhimg.com/v2-26e481d52ca3a7a49f377ac05fc4c897_r.jpg?source=1940ef5c

每个公司的每个职位要求会略有不同,所以不能一概而论,某一行没有写某项技术点也不能代表什么。以上更多的是参考以及自己在面试求职时可以按照这个方式进行梳理。

  • 阿里,在技术上会更加希望你有深度和广度,也善于把技术能应用到项目中,并有一定的学习能力。同时在工作中,要有责任心、沟通能力和解决问题的落地的能力。
  • 百度,同样希望可以精通一些框架的深层次内容,有一定的技术经验,更偏向于落地技能。同时也希望你是爱学习的面试者,最好有 Github 相关内容。工作中积极、主动、抗压,认真,善于沟通。
  • 腾讯,除了基础语言学习外,要有一些扩展,同时要深入理解语言特性。这可能和腾讯本身是用 C、C++ 有关,要知其然,知其所以然。同时希望在数据结构和算法上有一定的了解和认知,也可以在工作中有责任心、抗压能力以及问题分析和解决能力。

2.2 字节、美团、京东

https://pic1.zhimg.com/v2-8b29e8537be3fd3714ce7baa5ca9c712_r.jpg?source=1940ef5c

分析完上面三家公司,再看看这三家互联网对应聘者的要求。注意数据依旧是抽样,所以面试者在投递简历时,一定要自己拆解分析

  • 字节,更注重 Java 基础、算法、数据结构,同时对于常用的技术要有一定的了解深度。对代码方面要有良好的设计和代码品味追求,同时希望你关注业界最新技术,有好奇心和进取心。工作中,有产品意识。对于研发来说,产品意识很重要
  • 美团,美团的技术科目属于比较面的比较广和深的,尤其是字节码编程技术,在其他一些招聘中是没有看到的。除此之外更希望你有一定的学习能力,参与过 Github 开源项目,有技术钻研精神。在工作中,有较强的思维逻辑,难点攻克,复杂问题推进落地,责任感等。这可能也和美团的技术氛围有关,他们的技术博客做的也不错。_百度搜美团技术,https://tech.meituan.com/ _
  • 京东,各家公司都非常注重 Java 基本功,这些面试题可能不难但也很难。另外在常用框架和相应的技术深度上要有一定了解,尤其是各个框架的原理和实现机制,如果你能自己动手写一个,那么会更好。另外在技术经验上,可以有分布式、高并发等经验,也可以非常用的运用设计模式,编写出不错的代码。同时希望你有一定的学习能力,博客、开源代码、Github、Gitee 等。工作中,有过程控制意识、风险意识以及良好的沟通和解决问题的能力。

3. 考点总结

https://pica.zhimg.com/v2-149c1925a33de3c2a74eab4187f61b84_r.jpg?source=1940ef5c

综上,各家公司的招聘要求,梳理出七个方向的考点,包括:基本功底、常用技术、技术深度、技术经验、学习能力、工作能力、项目经验。

  • 基本功底,是一个程序员的主科目语言的学习程度的一个基本考察,这部分内容需要平时大量积累和总结。否则一本简单的 Java 书很难全部给你讲透彻,因为 Java 中包括了太多的内容,远不止 API 使用。
  • 常用技术,这个聊的是你的技术广度,和岗位技术匹配度。比如需要用到过 RPC,那你用过 Dubbo。如果你的公司暂时用的技术不多,或者还是处于单体服务,那么需要自己补充。
  • 技术深入,除了技术广度接下来就是技术深入,在你常用的技术栈中,你有多了解他们,了解源码吗、了解运行机制吗、了解设计原理吗。这部分内容常被人说是造火箭,但这部分内容非常重要,可以承上启下的贯穿个人修为和薪资待遇。
  • 技术经验,什么是技术经验呢?这是落地能力,除了你可能认为上面一些是纸上谈兵,是造火箭。那么接下来这部分内容就是你是否真造过一个火箭,真完成过一个难题。所以这部分是从结果证明,不是你会什么,而是你做过什么。
  • 学习能力,作为程序员你是否保持热情,是否依旧在积极努力的关注技术,是否为自己的成长不断添砖加瓦、是否还有好奇心和较强的求知欲。一般会从这里看你是不是一个真正的 Coder!
  • 工作能力,以上的种种能力,最终要体现到工作上,要能看出你的交付能力。否则即使你再优秀,也不能把你当成一个吉祥物。工作能力的体现,才是真的为团队、为部门、为公司,贡献价值的。
  • 项目经验,这项内容会根据不同公司的不同业务线而不同,就像你懂交易、支付,那么面试花呗、借呗、白条等工作岗位就会很吃香。

  • 面试也是一场有准备的战斗,知己知彼才能游刃有余。面试怎么面主要是看简历怎么写,最终是你来主导面试,还是被主导,更多也是依赖于你的技术身家。
  • 任何时候都需要主动学习、有技术眼光和魄力,既能吹得了造火箭的牛、也能落地出实际的产物、技能帮公司实现价值,也能让自己有一定的收入。才是你应该永久追求的目标,和突破瓶颈的价值。
  • 少一些躁动、少一些不安,多一些沉稳、多一些沉淀,只要你愿意积累就一定会突破瓶颈,都是这条路上的打工人,不要总让自己的大脑被别人牵着走,也不要活在别人嘴里。奥利给!