最近相继面试了BAT(字节, 阿里, 腾讯)的实习生, 收获满满. 在这里总结一下
前言
最近一段时间一直在准备面试,也没怎么好好的写博客文章,确实是有一点懈怠了。从上周到现在,相继面试了BAT三家大厂的实习。
本来想着在面试的时候录音,面试之后听一下录音然后进行总结,最后也没做。现在凭着记忆力来总结一下这几次面试的经历。
字节跳动
字节跳动应该是上周五(三月十三号)面试的,从下午两点开始,一直到下午六点,直接经历了三轮面试
结果:未录用
一面
这应该是我第一次参加正式的视频面试,是在牛客网上进行的。
开始的时候面试官让我介绍项目,这个我还是比较清楚的,就说了简历上的EZShare项目,分了两个版本,然后介绍第二个版本用了Redis缓存登录状态,然后面试官就把我打断了,问我为什么使用Redis缓存登录状态(中间说了不少细节)
我说应该是提升性能,在内存中肯定要比硬盘IO快,然后顺便可以熟悉一下Redis在项目中的使用;
结果面试官问我:使用了Redis就一定可以提升性能吗?
这个问题……,我说内存IO肯定要快过硬盘IO的吧,balabala
结果面试官继续问:你网站的访问量大概是多少?
我说基本上没什么访问量,毕竟没有域名,没有推广,而且在腾讯云上面部署,学生机提供的带宽也就是1MB/s,其实是很慢的。做这个项目主要是在内网朋友之间分享,然后熟练开发的一些技能什么的
然后就给了一个算法题:一个链表奇数递增,偶数递减,让最后转化为整体递增
其实题目很简单,但是确实是好久没刷题了(其实一直在看Java源码方面,确实疏忽了刷题,也高估了自己的记忆力)
所以开始给出了先把偶数装到集合里,这么垃圾的算法;
面试官说能不能In-place?
我想了一会,面试官提示了一下,先把链表拆分奇偶,然后再归并。
我坑坑巴巴的开始Coding,最后实在是太慢了,面试官让我停了……
然后问了几个问题:
- 什么是进程?什么是线程?有什么区别?
这个问题太经典了,我就说进程是操作系统级别的,线程在进程之中运行,真正干活的是线程。操作系统分配内存是按照进程分配,但真正使用内存的是进程,然后CPU是直接针对线程分配的……
面试官问,能不能具体在说说?
我想了想,实在不知道说什么(可能是操作系统底层类似于fork函数?)
然后基本上又重复了一遍上面……
面试官好像不太满意,然后问了下一个问题
- 进程间通信几种方式
应该是有六种,当时太紧张忘了,结果就说了一种RPC服务器间通信…(本质上是Socker通信)
面试官显然不满意,就让我说还有啥?
我想了想说管道吧,就是Linux里面的|
面试官说还有呢?
我实在是想不起来了……
进程间通信几种方式:
管道( pipe ):
管道包括三种:
- 普通管道PIPE: 通常有两种限制,一是单工,只能单向传输;二是只能在父子或者兄弟进程间使用
- 流管道s_pipe: 去除了第一种限制,为半双工,只能在父子或兄弟进程间使用,可以双向传输
- 命名管道:name_pipe:去除了第二种限制,可以在许多并不相关的进程之间进行通讯
信号量( semophore ) :
- 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段
消息队列( message queue ) :
- 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点
信号 ( sinal ) :
- 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生
共享内存( shared memory ) :
- 共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信
套接字( socket ) :
- 套接字也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信
显然面试官对我的回答很不满意啊~
- 讲一下数据库索引
我就说了说:最左匹配原则,数据结构等等;
然后面试官问我,现在有一个表有a,b两个字段分别加了索引,现在有个查询where a=xxx, b=xxx
,问最后走的是哪个索引?a还是b?
我说如果是组合索引的话,应该是都走,因为建了(a, b)其实就相当于建了(a), (a, b)
(这么说其实是有问题的,如果组合索引单独对b来说,它不符合最左匹配,不会单独走b索引的)
面试官就说,不是组合,就是单独的两个索引……
我说,a?
面试官问我为啥……
这个我真不知道。。。
最后这个问题也是不欢而散吧。。。
use test; drop table if exists `t_index_test`; create table t_index_test ( `a` char(10) not null, `b` char(10) not null, `c` char(10) not null, `d` char(10) not null, # 单独索引a,b,c,d # index (`a`), # index (`b`), # index (`c`), # index (`d`) # 单独索引d,c,b,a # index (`d`), # index (`c`), # index (`b`), # index (`a`) # 组合索引(a,b,c,d) index (`a`, `b`, `c`, `d`) # 组合索引(d,c,b,a) # index (`d`, `c`, `b`, `a`) ) engine = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8; show index from t_index_test; INSERT INTO t_index_test (`a`, `b`, `c`, `d`) values ('a1', 'b1', 'c1', 'd1'); INSERT INTO t_index_test (`a`, `b`, `c`, `d`) values ('a2', 'b2', 'c2', 'd2'); INSERT INTO t_index_test (`a`, `b`, `c`, `d`) values ('a3', 'b3', 'c3', 'd3'); INSERT INTO t_index_test (`a`, `b`, `c`, `d`) values ('a4', 'b4', 'c4', 'd4'); INSERT INTO t_index_test (`a`, `b`, `c`, `d`) values ('a5', 'b5', 'c5', 'd5'); INSERT INTO t_index_test (`a`, `b`, `c`, `d`) values ('a6', 'b6', 'c6', 'd6'); INSERT INTO t_index_test (`a`, `b`, `c`, `d`) values ('a7', 'b7', 'c7', 'd7'); INSERT INTO t_index_test (`a`, `b`, `c`, `d`) values ('a8', 'b8', 'c8', 'd8'); INSERT INTO t_index_test (`a`, `b`, `c`, `d`) values ('a9', 'b9', 'c9', 'd9'); explain select a, b from t_index_test where a = 'a1' and b = 'b2'; explain select * from t_index_test where b = 'b2' and a = 'a2'; explain select * from t_index_test where b = 'b1' and c = 'c1'; explain select * from t_index_test where c = 'c2' and d = 'd2';
① 单独索引a,b,c,d
mysql> show index from t_index_test; +--------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression | +--------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | t_index_test | 1 | a | 1 | a | A | 0 | NULL | NULL | | BTREE | | | YES | NULL | | t_index_test | 1 | b | 1 | b | A | 0 | NULL | NULL | | BTREE | | | YES | NULL | | t_index_test | 1 | c | 1 | c | A | 0 | NULL | NULL | | BTREE | | | YES | NULL | | t_index_test | 1 | d | 1 | d | A | 0 | NULL | NULL | | BTREE | | | YES | NULL | +--------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ 4 rows in set (0.00 sec)
查询结果:
mysql> explain select a, b from t_index_test where a = 'a1' and b = 'b2'; +----+-------------+--------------+------------+------+---------------+------+---------+-------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------------+------------+------+---------------+------+---------+-------+------+----------+-------------+ | 1 | SIMPLE | t_index_test | NULL | ref | a,b | a | 30 | const | 1 | 11.11 | Using where | +----+-------------+--------------+------------+------+---------------+------+---------+-------+------+----------+-------------+ mysql> explain select * from t_index_test where b = 'b2' and a = 'a2'; +----+-------------+--------------+------------+------+---------------+------+---------+-------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------------+------------+------+---------------+------+---------+-------+------+----------+-------------+ | 1 | SIMPLE | t_index_test | NULL | ref | a,b | a | 30 | const | 1 | 11.11 | Using where | +----+-------------+--------------+------------+------+---------------+------+---------+-------+------+----------+-------------+ mysql> explain select * from t_index_test where b = 'b1' and c = 'c1'; +----+-------------+--------------+------------+------+---------------+------+---------+-------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------------+------------+------+---------------+------+---------+-------+------+----------+-------------+ | 1 | SIMPLE | t_index_test | NULL | ref | b,c | b | 30 | const | 1 | 11.11 | Using where | +----+-------------+--------------+------------+------+---------------+------+---------+-------+------+----------+-------------+ mysql> explain select * from t_index_test where c = 'c2' and d = 'd2'; +----+-------------+--------------+------------+------+---------------+------+---------+-------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------------+------------+------+---------------+------+---------+-------+------+----------+-------------+ | 1 | SIMPLE | t_index_test | NULL | ref | c,d | c | 30 | const | 1 | 11.11 | Using where | +----+-------------+--------------+------------+------+---------------+------+---------+-------+------+----------+-------------+
可见四个查询都走了索引(rows都为1),同时where的前后顺序在SQL执行器内部应该是做了优化的!
② 单独索引d,c,b,a
mysql> show index from t_index_test; +--------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression | +--------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | t_index_test | 1 | d | 1 | d | A | 0 | NULL | NULL | | BTREE | | | YES | NULL | | t_index_test | 1 | c | 1 | c | A | 0 | NULL | NULL | | BTREE | | | YES | NULL | | t_index_test | 1 | b | 1 | b | A | 0 | NULL | NULL | | BTREE | | | YES | NULL | | t_index_test | 1 | a | 1 | a | A | 0 | NULL | NULL | | BTREE | | | YES | NULL | +--------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
注意:索引的顺序是不同的!
查询结果:
mysql> explain select a, b from t_index_test where a = 'a1' and b = 'b2'; +----+-------------+--------------+------------+------+---------------+------+---------+-------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------------+------------+------+---------------+------+---------+-------+------+----------+-------------+ | 1 | SIMPLE | t_index_test | NULL | ref | b,a | b | 30 | const | 1 | 11.11 | Using where | +----+-------------+--------------+------------+------+---------------+------+---------+-------+------+----------+-------------+ mysql> explain select * from t_index_test where b = 'b1' and c = 'c1'; +----+-------------+--------------+------------+------+---------------+------+---------+-------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------------+------------+------+---------------+------+---------+-------+------+----------+-------------+ | 1 | SIMPLE | t_index_test | NULL | ref | c,b | c | 30 | const | 1 | 11.11 | Using where | +----+-------------+--------------+------------+------+---------------+------+---------+-------+------+----------+-------------+ mysql> explain select * from t_index_test where c = 'c2' and d = 'd2'; +----+-------------+--------------+------------+------+---------------+------+---------+-------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------------+------------+------+---------------+------+---------+-------+------+----------+-------------+ | 1 | SIMPLE | t_index_test | NULL | ref | d,c | d | 30 | const | 1 | 11.11 | Using where | +----+-------------+--------------+------------+------+---------------+------+---------+-------+------+----------+-------------+
可见此时也是走了索引的
但是,走的索引和情况①是不同的!
结论:会走先遇到的索引,即和建表时索引的声明顺序有关
③ 组合索引(a,b,c,d)
mysql> show index from t_index_test; +--------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression | +--------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | t_index_test | 1 | a | 1 | a | A | 0 | NULL | NULL | | BTREE | | | YES | NULL | | t_index_test | 1 | a | 2 | b | A | 0 | NULL | NULL | | BTREE | | | YES | NULL | | t_index_test | 1 | a | 3 | c | A | 0 | NULL | NULL | | BTREE | | | YES | NULL | | t_index_test | 1 | a | 4 | d | A | 0 | NULL | NULL | | BTREE | | | YES | NULL | +--------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
注意到此时key名称都为a!(即是同一个组合索引)
查询结果:
mysql> explain select a, b from t_index_test where a = 'a1' and b = 'b2'; +----+-------------+--------------+------------+------+---------------+------+---------+-------------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------------+------------+------+---------------+------+---------+-------------+------+----------+-------------+ | 1 | SIMPLE | t_index_test | NULL | ref | a | a | 60 | const,const | 1 | 100.00 | Using index | +----+-------------+--------------+------------+------+---------------+------+---------+-------------+------+----------+-------------+ mysql> explain select * from t_index_test where b = 'b1' and c = 'c1'; +----+-------------+--------------+------------+-------+---------------+------+---------+------+------+----------+--------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------------+------------+-------+---------------+------+---------+------+------+----------+--------------------------+ | 1 | SIMPLE | t_index_test | NULL | index | a | a | 120 | NULL | 9 | 11.11 | Using where; Using index | +----+-------------+--------------+------------+-------+---------------+------+---------+------+------+----------+--------------------------+ mysql> explain select * from t_index_test where c = 'c2' and d = 'd2'; +----+-------------+--------------+------------+-------+---------------+------+---------+------+------+----------+--------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------------+------------+-------+---------------+------+---------+------+------+----------+--------------------------+ | 1 | SIMPLE | t_index_test | NULL | index | a | a | 120 | NULL | 9 | 11.11 | Using where; Using index | +----+-------------+--------------+------------+-------+---------------+------+---------+------+------+----------+--------------------------+
可以看到:
查询a=xxx,b=xxx时
使用到了索引
using index;
,并且rows为1,说明直接返回了一列!查询b=xxx,c=xxx或者c=xxx,d=xxx时
显示
Using whre Using index;
,表示:查询的列被索引列覆盖,并且where筛选条件是索引列之一但不是索引的前导列说明无法直接通过索引查找查询到符合条件的数据
可以看到rows为9(即表中所有行!)
所以此时并没有使用索引!
上面的分析其实也是符合索引最左匹配原则的!
④ 组合索引(d,c,b,a)
mysql> show index from t_index_test; +--------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression | +--------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | t_index_test | 1 | d | 1 | d | A | 0 | NULL | NULL | | BTREE | | | YES | NULL | | t_index_test | 1 | d | 2 | c | A | 0 | NULL | NULL | | BTREE | | | YES | NULL | | t_index_test | 1 | d | 3 | b | A | 0 | NULL | NULL | | BTREE | | | YES | NULL | | t_index_test | 1 | d | 4 | a | A | 0 | NULL | NULL | | BTREE | | | YES | NULL | +--------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
注意到:索引名称为d
查询结果:
mysql> explain select a, b from t_index_test where a = 'a1' and b = 'b2'; +----+-------------+--------------+------------+-------+---------------+------+---------+------+------+----------+--------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------------+------------+-------+---------------+------+---------+------+------+----------+--------------------------+ | 1 | SIMPLE | t_index_test | NULL | index | d | d | 120 | NULL | 9 | 11.11 | Using where; Using index | +----+-------------+--------------+------------+-------+---------------+------+---------+------+------+----------+--------------------------+ mysql> explain select * from t_index_test where b = 'b1' and c = 'c1'; +----+-------------+--------------+------------+-------+---------------+------+---------+------+------+----------+--------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------------+------------+-------+---------------+------+---------+------+------+----------+--------------------------+ | 1 | SIMPLE | t_index_test | NULL | index | d | d | 120 | NULL | 9 | 11.11 | Using where; Using index | +----+-------------+--------------+------------+-------+---------------+------+---------+------+------+----------+--------------------------+ mysql> explain select * from t_index_test where c = 'c2' and d = 'd2'; +----+-------------+--------------+------------+------+---------------+------+---------+-------------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------------+------------+------+---------------+------+---------+-------------+------+----------+-------------+ | 1 | SIMPLE | t_index_test | NULL | ref | d | d | 60 | const,const | 1 | 100.00 | Using index | +----+-------------+--------------+------------+------+---------------+------+---------+-------------+------+----------+-------------+
与上面类似,此时在查询(d,c)时使用到了索引~
- 讲一下Java中的CAS
CAS,CompareAndSwap,比较和交换,通过比较一个expectedValue是否符合预期来完成相加原子性操作等;同时对于ABA问题,可以通过引入version,即版本号来解决
我以为答得已经很不错了,结果面试官问我CAS底层怎么实现的?硬件怎么支持的?
我:???可能书上这么说的,我也没往细致去看……
面试官:如果让你设计呢?
我:这个可能都要涉及到特别底层的了,可能在每个CPU Core中都有一个特定的电路直接通过位处理直接实现了这个功能……
面试官:嗯……我觉得你在下面可以看一下Intel的底层是怎么设计的。。。
我:好的……
最后感觉面试官还是不太满意…,但是还是结束了
我以为一面已经凉凉了,直接笔记本都关机了……,结果过了两分钟,字节那边打电话过来,直接进行二面……
二面
二面面试官其实特别好啊,但是确实是我算法实在忘了太多了……
上来自我介绍,项目介绍,balabala
然后直入主题算法题:无限大的棋盘从(0,0) -> (x,y)最少步数。。。
(现在想来,这不是明显的八个方向的BFS,当时都没想到,我无语了)
这一道题一直没做出来,面试官还一直提示(想象成一棵八节点的树),气氛尴尬到了极点……,最后我说,图论的我确实不怎么会。然后换了一道题:
给定一个数组,arr[i]代表棒子的高度,求积水面积
结果也没做出来
现在想来并不是很难。。。
求出每个柱子上面能够存多少水,然后将每根柱子的存水量相加便能得到总的存水量
为求出每根柱子上能够存多少水,就要求出每根柱子左边最高的和右边最高柱子,然后用两者的最小值减去当前柱子的高度
例如:(5,2,3,2,4)
从左到右第二根柱子的高度为2,它左边最高柱子的值为5,右边最高柱子的值为4,因此它的最大存水量为Min(4,5) - 2 = 2
所以建立left,right两个数组,直接求arr[i]左右最大值即可。。。
两个面试题都没做出来,心态有点爆炸,问的问题现在也记不太清了(好像就问了一两个……)
然后就直接结束了……
这时候我以为已经结束了,结果过了两分钟,字节打电话三面。。。
三面
介绍自己,介绍项目
然后问了Java并发一些问题:比如锁,内存模型之类的(答得还凑合吧~)
然后没问算法,直接让我手写一个阻塞队列……
我前几天确实看了阻塞队列相关的一些内容,但是手写阻塞队列……硬着头皮用ReentrantLock和Condition + LinkedList写了一个无界的;
面试官说,有界队列……
我又加了一个size,加了个Condition……
结果没捕获InterruptedException,然后Condition.signal()写成了notify()…(这个我看出来了,但是确实忘了方法名……)
然后面试官问我notify和notifyAll的区别……,我答了一下然后改成notifyAll……(还是错的~)
其实代码基本逻辑写出来了,但是确实又不少小问题。。。
面试官好像不是特别满意。。。
然后说你用过Redis是吧,说说LRU算法?代码写出来
(其实这个是LeetCode的一个题目,用LinkedHashMap很容易啊)
但是面试官说用LinkedList和HashMap实现(当时也不知道怎么想的,这些集合的源码都看过了,还是没答出来……)
最后这个也没写出来。。。
面试官说你有什么想问我的?
我问了问我面试表现(心里其实很清楚了~),然后问了一些学习方法之类的;面试官挺好的,从横向和纵向跟我讲了讲,然后面试就结束了~
总结
这是第一次在牛客网上视频面试,整个面试过程四个小时左右。由于算法这方面的疏忽吧,导致面试的时候算法题一直做不出来,最后心态爆炸。。。
其次就是确实在数据结构,Redis底层这种还是不太熟悉,准备的大多数是框架相关的东西,最后也没有问。。。
总的来说第一次面试还是相当失败的。。。
腾讯
一面
一面依然是在牛客网面试,真的是要克服算法的心理障碍……,其实是抱着破罐破摔去的
果不其然,上来自我介绍,然后直接一个算法题:LeetCode 第一题TwoSum……
我一看,这题目这么简单= = ,两分钟写完,面试官看了一下说少了数组判空的条件,我又加了:
if (arr == null || arr.lenght == 0) throw new RuntimeException("Invalid parameter!");
面试官说如果为空直接抛异常是吧?
我说是的
然后就问了Java里面异常处理机制Exception和Error?
这个挺简单的,然后就答了……
然后问了Java垃圾回收,分代,回收算法。
我从分代,到算法,到GC,到YoungGC,OldGC,MajorGC,FullGC给他讲了一遍,讲到GC的时候,把我打断了……(可能是我太啰嗦了)
接下来问Java线程池?
这个我是看过源码的,所以答得还可以,包括四种类型,传入不同参数的时候的类型之类的。
接下来问我HTTPS的过程?
我先详细讲了中间人攻击,为什么要HTTPS,然后讲了HTTPS的过程就是先非对称加密,确定证书,加密salt,然后再对称加密;
然后面试官问我HTTPS一定安全吗?会不会遭到工具?
我说会的,确定key之前如果已经存在中间人,还是会被截取;
然后又问了几个问题,记不太清了。面试官貌似还挺满意,最后说今天就到这吧~
二面
二面我以为也是在牛客网上面试,结果最后五分钟的时候,发现是在腾讯会议上面面试…,花了两分钟下好,安装好软件,然后刚进去就开始了。。。
面试的是个小姐姐。上来先让我做自我介绍,然后问了项目的问题,挺详细的。
然后问了我的一些经历,比如:为什么学计算机了?周围学习氛围?
然后问了几个问题:
- 快排时间复杂度?平均?最差?
我大概说了一下快排过程,最差的情况,然后说了时间复杂度,准备说一些优化方法的时候(我之前有写过一些排序优化的文章),把我打断了(可能是我太啰嗦了。。。)
- 在url输入链接经历的过程
这题目其实很经典了,我先问了一下是http还是https?因为苹果最近的标准规定了iOS商店软件请求必须是HTTPS!
结果面试官说讲过程就行了。。。
我就说了http的:
首先从本地hosts文件找dns,没找到到你路由缓存找,也没找到到运营商找,找到之后获得ip,然后浏览器请求,后端处理请求返回结果
其实还有好多细节可以说, 比如:
- 浏览器一开始会帮你在url最后面添加
/
,这个其实挺细节的 - 建立连接过程?三次握手?
- 断开连接?
- get?post?
- 流量控制?(划窗算法)
- ……
由于时间关系,并没有展开。。。
- 你平常是怎么学习的?为什么知道这么多?
我说其实我比起那些科班出身的基础差得多,大部分可能是由于兴趣,就是上面问到的问题我平常也问过我自己,还有比如推荐算法:为什么在b站或者淘宝能够准确推荐给你商品?
- 你知道什么流行的技术?你想学习的?
我说太多了,比如容器虚拟化Docker,Docker-compose,K8S而且我现在就在用docker部署,本机上面没有软件,只有容器;还有微服务比如Spring Cloud这一类;此外就是大数据也有兴趣,比如阿里的Alink,Blink,Flink,Spark这种实时数据流处理,但是一直没时间学……
- 你评价一下你自己的优缺点?
我说可能我是单线程生物,专注但是死脑筋……balabala
最后面试官说今天就到这吧,二十多分钟就结束了。。。
目前在等待三轮面试……
阿里
二面
阿里之前的一面是一个师兄面我的,详细见:记一次面试前和阿里员工交流感悟
二面的时候是在星期六晚上七点半左右,整个面试过程大概四十五分钟,问的问题很多,很杂
开始的时候先让我做自我介绍。
然后问我的项目:Predictor
我说这个项目其实是我的研究生项目,和Java Web关系其实不大……
然后我简单介绍了一下,用python和神经网络处理……;
面试官问:数据量有多大怎么处理的?
我说一个bin文件大概100多个G,数据发送的时候都是二进制存储,然后处理的时候先分文件成多个batch,然后分batch流读入处理……
面试官:不是实时处理的是吧?
我说是的,因为这个其实故障诊断不需要实时性
面试官:那你知道的实时处理的有哪些?实时流处理有什么用?和
比如阿里的Alink,Blink和Flink,然后还有最近比较热的Spark,然后说了一下我有学一点Scala等待;
面试官:除了这个项目,其他的是Java开发的是吧?
我说是的
然后就问了几个Java问题:
- 类加载和ClassLoader知道吗?
我讲了一下类加载的过程(这个之前看周志明大牛的《深入理解Java虚拟机》的时候很清楚,但是面试的时候有点忘了……)
首先我先说了什么时候会发生加载(三种情况),然后说了类加载的过程,我说了一共五步(但是就记住了三步……,无语)
类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading)7个阶段
其中准备、验证、解析3个部分统称为连接(Linking)
加载、验证、准备、初始化和卸载这5个阶段的顺序是确定的,类的加载过程必须按照这种顺序按部就班地开始
而解析阶段则不一定:它在某些情况下可以在初始化阶段之后再开始,这是为了支持Java语言的运行时绑定(也称为动态绑定或晚期绑定)
想了一会实在是想不出来了……
就说最后是初始化,但是这个初始化填入的是默认值,最后才会调<init>
方法初始化。。。
下来又看了看。。。
- 讲讲HashMap
因为HashMap这个我写过源码分析的文章,所以特别熟啊,包括:
- 数组大小为什么是二次幂?两倍扩容?
- 什么时候链表转红黑树?什么时候转回去?为什么取6,8?泊松分布
- 什么时候扩容?factor?
- 为什么头插法改成尾插法?
- 在扩容rehash的时候JDK源码是怎么巧妙的转化的?(这个源码非常巧妙)
- JDK8后加入的Stream操作底层的支持Spliterator类等等……
这里推荐我写过的一篇文章,里面解释了所有疑问:
- Linux一些问题
抓包?我说wireshark。面试官说命令行的呢?我说这个不太清楚,不过mtr命令可以ping地址并且找出整个数据包经过的路由
查网络端口占用的命令?netstat
- 问题排查:现在Java部署在linux服务器上,出现100%CPU占有率
这个问题网上是有的,但是我没看,当时就说可能是频繁创建线程,比如用户一直发起请求;或者一直GC;或者文件IO等待;
面试官好像不太满意:不是让你说问题,说说怎么排查;
我说可以通过java带的一些工具,比如jdump(这是啥?当时说错了),还有阿里的arthas。
但是上面这些我都没用过…,我用的是jconsole
面试官说:重点说排查过程!
我说:首先可以通过jconsole远程连接服务器,然后通过查看jconsole的图形界面中的曲线去排查
面试官:具体点!
我说:比如频繁GC的话,可能可以看到堆内存的分配一直在抖动,忽上忽下这种
面试官:再具体排查?年轻代?老年代?
我说:比如可以选择jconsole中的年轻代老年代,查看堆内存抖动情况?然后就是如果线程分配的话,也可以看到线程频繁的创建和销毁等等……
面试官也没再追问了……
还有一些其他的专业问题吧……太多了记不太清了。。。
- 你不是科班的为什么考研的时候不转计算机?
我想转,但是当时已经大三了……,其实研究生复试的时候拿的是计算机的四大天书回家的。但是最后考上研了,还是上了……
- 你周围计算机氛围?
- 你在实习时的一些收获?
- 如果阿里最后没有录用,还会继续学习计算机吗?
Absolutely~ 情熱がいつもある!
- 你知道的一些流行的技术有哪些?
和腾讯回答的差不多,Docker容器虚拟化,微服务SpringCloud,大数据相关Flink,Spark等等;
- 未来的一些学习计划
首先会打好计算机的基础,比如计算机网络,数据结构和算法这种(其实以前都看过,但是不是科班的,没有经过期末考试等这种洗礼,印象还是不够深刻)
然后最近流行的技术一定会去学习,比如CI/CD,容器虚拟化Docker,容器编排K8S,大数据也想学习但是确实没时间(B站有全集视频!)。哎……
最后面试官说今天就到这里吧~
总结
经过了BAT面试的洗礼,让我意识到自己确实和真正的科班差距很大,尤其是字节跳动(算法题真的是很重要)
其次就是思维僵化问题,很容易陷入这种陷阱当中;
最后就是一边学习还要复习。其实面试绝大部分内容虽然不是科班,但是在自己的学习路线中或多或少都是有所学习的,但是很多问题其实都忘记了!只有温故而知新!
鸣谢
文章最后想感谢那些在我面试之路上一直关系鼓励我的人:比如在上海工作的朋友,在北京做前端开发的朋友;此外还有阿里的师兄们给我提出的宝贵意见;最重要的,还有那些爱我的人和我爱的人。
最开始面试BAT的时候其实就是抱着必死的心态,毕竟自己非科班,论专业程度,论项目经验,可能都不如他们,所以只是看看自己自学了这么久,大概是个什么水平吧~
最后的最后,感谢互联网,让我认识了这么多志同道合一起学习和讨论技术的朋友们~❤
如果觉得文章写的不错, 可以关注微信公众号: Coder张小凯
内容和博客同步更新~