小伙伴们,大家新年好,明天给大家分享字节跳动抖音电商的面经,心愿对小伙伴们有所帮忙~
面试官:你好,我是字节跳动的面试官 xxx,请问是大彬吗?
大彬:面试官,您好,我是大彬
面试官:当初不便面试吗?
大彬:嗯嗯,能够的
面试官:那咱们当初开始面试吧
面试官 : 看你简历上写了相熟汇合相干内容,你理解 HashMap 吗?讲一下 HashMap 的 put 办法?
独白:果然一上来就是 HashMap…
大彬:HashMap 实现了 Map 接口,用于保留键值对映射。其底层是应用数组 + 链表 + 红黑树(JDK1.8 减少了红黑树局部)实现的。
大彬:它的 put 办法过程如下:
- 如果 table 没有初始化就先进行初始化过程
- 应用 hash 算法计算 key 的索引
- 判断索引处有没有存在元素,没有就直接插入
- 如果索引处存在元素,则遍历插入,有两种状况,一种是链表模式就间接遍历到尾端插入,一种是红黑树就依照红黑树结构插入
- 链表的数量大于阈值 8,就要转换成红黑树的构造
- 增加胜利后会查看是否须要扩容
面试官 : 嗯,刚刚你提到 HashMap 的扩容,具体讲一下?
独白:emm,给本人挖坑了 …
大彬:以 JDK1.8 为例,当往 HashMap 放入元素时,如果元素个数大于 threshold 时,会进行扩容,应用 2 倍容量的数组代替原有数组。
大彬 :因为数组的容量是以 2 的幂次方扩容的,那么一个 Entity 在扩容时,新的地位要么在 原地位 ,要么在 原长度 + 原地位 的地位。
大彬 :起因是数组长度变为原来的 2 倍,体现在二进制上就是 多了一个高位参加数组下标计算。
大彬 :也就是说,在元素拷贝过程不须要从新计算元素在数组中的地位,只须要看看原来的 hash 值新增的那个 bit 是 1 还是 0,是 0 的话索引没变,是 1 的话索引变成“原索引 +oldCap”(依据e.hash & (oldCap - 1) == 0
判断)。
大彬:这样能够省去从新计算 hash 值的工夫,而且因为新增的 1bit 是 0 还是 1 能够认为是随机的,因而 resize 的过程会平均的把之前的抵触的节点扩散到新的 bucket。
面试官 : 小伙子,根底还算不错。看你简历上写了精通 MySQL,来讲讲一下 MySQL 的索引构造?
独白:卧槽,当前再也不敢写精通了 …. 还好昨天背了大厂面试手册,当初一点都不慌,须要的能够到公众号【程序员大彬】后盾回复【手册】获取大厂面试材料
大彬:MySQL 数据库应用最多的索引类型是 BTREE 索引,底层基于 B + 树数据结构来实现。
大彬:B+ 树是基于 B 树和叶子节点程序拜访指针进行实现,它具备 B 树的平衡性,并且通过程序拜访指针来进步区间查问的性能。
大彬:进行查找操作时,首先在根节点进行二分查找,找到 key 所在的指针,而后递归地在指针所指向的节点进行查找。直到查找到叶子节点,而后在叶子节点上进行二分查找,找出 key 所对应的数据项。
面试官 : 为什么索引要用 B + 树来实现呢,而不是用二叉树?
大彬:B+ 树有个特点,就是够矮够胖,能无效地缩小拜访节点次数从而进步性能。
大彬:尽管二叉树也有很好的查找性能 log2N,然而当 N 比拟大的时候,树的深度比拟高。数据查问的工夫次要依赖于磁盘 IO 的次数,二叉树深度越大,查找的次数越多,性能越差。最坏的状况会进化成链表。所以,B+ 树更适宜作为 MySQL 索引构造。
面试官 : 那又为什么不必 B 树呢?
独白:当初面试也太卷了趴,这是要造火箭啊 …
大彬:因为 B 树的分支结点存储着数据,咱们要找到具体的数据,须要进行一次中序遍历按序来扫。而因为 B + 树的数据都存储在叶子结点中,叶子结点均为索引,不便扫库,只须要扫一遍叶子结点即可。所以 B + 树更加适宜在区间查问的状况,而在数据库中基于范畴的查问是十分频繁的,所以 B + 树更适宜用于数据库索引。
面试官 : 晓得汇集索引吗?
大彬:汇集索引严格来说并不是索引类型,而是一种数据存储形式,具体细节依赖于其实现形式。如 innodb 汇集索引的叶子节点寄存了整张表的行记录。
大彬:汇集索引相似字典的拼音目录。表中的数据依照汇集索引的规定来存储的。就像新华字典,整本字典是依照 A - Z 的程序来排列。这也是一个表只能有一个汇集索引的起因。
面试官 : 那聚簇索引相比非聚簇索引有什么长处?
大彬 :1. 数据拜访更快,因为聚簇索引将索引和数据保留在同一个 B + 树中,因而从聚簇索引中获取数据比非聚簇索引更快。
大彬:2. 汇集索引叶子节点的存储是逻辑上间断的,所以对于主键的排序查找和范畴查找速度会更快。
面试官 : 嗯,问点其余的,线程池晓得吧?
大彬:线程池,顾名思义,就是一个治理线程的池子。
面试官 : 那为什么应用线程池呢?
大彬:之所以应用线程池,次要有三点起因:
- 升高资源耗费。通过反复利用已创立的线程升高线程创立和销毁造成的耗费。
- 进步响应速度。当工作达到时,能够不须要等到线程创立就能立刻执行。
- 进步线程的可管理性。对立治理线程,防止零碎创立大量同类线程而导致耗费完内存。
面试官 : 嗯,那你讲一下线程池的几个参数?
独白:老八股文了嘿嘿~
大彬:先来看看 ThreadPoolExecutor 的通用构造函数:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler);
大彬:其中有 7 个参数。别离是 corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler
大彬:corePoolSize。当有新工作时,如果线程池中线程数没有达到线程池的根本大小,则会创立新的线程执行工作,否则将工作放入阻塞队列。当线程池中存活的线程数总是大于 corePoolSize 时,应该思考调大 corePoolSize。
大彬:maximumPoolSize。当阻塞队列填满时,如果线程池中线程数没有超过最大线程数,则会创立新的线程运行工作。否则依据回绝策略解决新工作。非核心线程相似于长期借来的资源,这些线程在闲暇工夫超过 keepAliveTime 之后,就应该退出,防止资源节约。
大彬:BlockingQueue。存储期待运行的工作。
大彬 :keepAliveTime。 非核心线程 闲暇后,放弃存活的工夫,此参数只对非核心线程无效。设置为 0,示意多余的闲暇线程会被立刻终止。
大彬:TimeUnit。工夫单位,具体如下:
TimeUnit.DAYS
TimeUnit.HOURS
TimeUnit.MINUTES
TimeUnit.SECONDS
TimeUnit.MILLISECONDS
TimeUnit.MICROSECONDS
TimeUnit.NANOSECONDS
大彬:ThreadFactory。每当线程池创立一个新的线程时,都是通过线程工厂办法来实现的。在 ThreadFactory 中只定义了一个办法 newThread,每当线程池须要创立新线程就会调用它。
public class MyThreadFactory implements ThreadFactory {
private final String poolName;
public MyThreadFactory(String poolName) {this.poolName = poolName;}
public Thread newThread(Runnable runnable) {return new MyAppThread(runnable, poolName);// 将线程池名字传递给构造函数,用于辨别不同线程池的线程
}
}
大彬:RejectedExecutionHandler。当队列和线程池都满了时,依据回绝策略解决新工作。
AbortPolicy:默认的策略,间接抛出 RejectedExecutionException
DiscardPolicy:不解决,间接抛弃
DiscardOldestPolicy:将期待队列队首的工作抛弃,并执行当前任务
CallerRunsPolicy:由调用线程解决该工作
面试官 : 好的。你理解 Spring AOP 吗?
大彬:AOP,其实就是面向切面编程,将一些公共逻辑(事务管理、日志、缓存等)封装成切面,跟业务代码进行拆散,能够缩小零碎的反复代码和升高模块之间的耦合度。切面就是那些与业务无关,但所有业务模块都会调用的公共逻辑。
大彬:Spring AOP 是通过动静代理技术实现的。
面试官 : 哦,那动静代理的实现形式有哪些?
大彬:动静代理技术的实现形式有两种:
- 基于接口的 JDK 动静代理。
- 基于继承的 CGLib 动静代理。在 Spring 中,如果指标类没有实现接口,那么 Spring AOP 会抉择应用 CGLIB 来动静代理指标类。
面试官 : 你刚刚提到 CGlib 动静代理,能具体介绍下吗?
大彬:CGLIB,就是 Code Generator Library,它是一个弱小的、高性能的代码生成库,被广泛应用于 AOP 框架中,用以提供办法拦挡操作。
大彬:CGLIB 代理次要通过对字节码的操作,为对象引入间接级别,以管制对象的拜访。
大彬 :CGLib 动静代理绝对于 JDK 动静代理局限性就小很多,指标对象不须要实现接口,底层是通过 继承指标对象产生代理子对象。
面试官:不错,好好筹备二面吧~
码字不易,如果感觉对你有帮忙,能够 点个赞 激励一下!