2020腾讯面试题!附答案

一面:
集合有哪些:
List(ArrayList Linklist ) set(Set Treeset Hashset) map(Hashmap currentHashmap hashtable )
2020腾讯面试题!附答案mysql

arraylist和linkedlist区别
一个是基于数组的实现 一个是基于的链表的实现面试

hashmap怎么扩容(多线程扩容为何会死循环),put过程redis

出现的是链表的闭环。
2020腾讯面试题!附答案算法

concurrentHashMap 1.7和1.8spring

1.7是采用采用的仍是分段锁的机制 1.8采用的是CAS机制来实现的。sql

接口和抽象类区别数据库

JVM内存分区
2020腾讯面试题!附答案编程

新生代:
eden,survivor_from, survivor_to设计模式

垃圾回收算法:数组

三种 标记清除 复制算法 标记整理算法

PretenureSizeThreshold,maxTenuringThreshold(默认15)
若是并发的线程数量不少,而且每一个线程都是执行一个时间很短的任务就结束了,这样频繁建立线程就会大大下降系统的效率,由于频繁建立线程和销毁线程须要时间。

1线程池状态
在ThreadPoolExecutor中定义了一个volatile变量,另外定义了几个static final变量表示线程池的各个状态:

volatile int runState;

static final int RUNNING = 0;

static final int SHUTDOWN = 1;

static final int STOP = 2;

static final int TERMINATED = 3;

runState表示当前线程池的状态,它是一个volatile变量用来保证线程之间的可见性;

下面的几个static final变量表示runState可能的几个取值。

当建立线程池后,初始时,线程池处于RUNNING状态;

若是调用了shutdown()方法,则线程池处于SHUTDOWN状态,此时线程池不可以接受新的任务,它会等待全部任务执行完毕;

若是调用了shutdownNow()方法,则线程池处于STOP状态,此时线程池不能接受新的任务,而且会去尝试终止正在执行的任务;

当线程池处于SHUTDOWN或STOP状态,而且全部工做线程已经销毁,任务缓存队列已经清空或执行结束后,线程池被设置为TERMINATED状态。

2任务的执行
ThreadPoolExecutor类中其余的一些比较重要成员变量:

rivate final BlockingQueue<Runnable> workQueue; //任务缓存队列,用来存放等待执行的任务

private final ReentrantLock mainLock = new ReentrantLock(); //线程池的主要状态锁,对线程池状态(好比线程池大小//、runState等)的改变都要使用这个锁

private final HashSet<Worker> workers = new HashSet<Worker>(); //用来存放工做集

private volatile long keepAliveTime; //线程存货时间

private volatile boolean allowCoreThreadTimeOut//是否容许为核心线程设置存活时间

private volatile int corePoolSize; //核心池的大小(即线程池中的线程数目大于这个参数时,提交的任务会被放进任务缓存队列)

private volatile int maximumPoolSize; //线程池最大能容忍的线程数

private volatile int poolSize; //线程池中当前的线程数

private volatile RejectedExecutionHandler handler; //任务拒绝策略

private volatile ThreadFactory threadFactory; //线程工厂,用来建立线程

private int largestPoolSize; //用来记录线程池中曾经出现过的最大线程数

private long completedTaskCount; //用来记录已经执行完毕的任务个数

1)首先,要清楚corePoolSize和maximumPoolSize的含义;

2)其次,要知道Worker是用来起到什么做用的;

3)要知道任务提交给线程池以后的处理策略,这里总结一下主要有4点:

若是当前线程池中的线程数目小于corePoolSize,则每来一个任务,就会建立一个线程去执行这个任务;

若是当前线程池中的线程数目>=corePoolSize,则每来一个任务,会尝试将其添加到任务缓存队列当中,若添加成功,则该任务会等待空闲线程将其取出去执行;若添加失败(通常来讲是任务缓存队列已满),则会尝试建立新的线程去执行这个任务;

若是当前线程池中的线程数目达到maximumPoolSize,则会采起任务拒绝策略进行处理;

若是线程池中的线程数量大于 corePoolSize时,若是某线程空闲时间超过keepAliveTime,线程将被终止,直至线程池中的线程数目不大于corePoolSize;若是容许为核心池中的线程设置存活时间,那么核心池中的线程空闲时间超过keepAliveTime,线程也会被终止。

3线程池中的线程初始化
默认状况下,建立线程池以后,线程池中是没有线程的,须要提交任务以后才会建立线程。

4任务缓存队列及排队策略
在前面咱们屡次提到了任务缓存队列,即workQueue,它用来存放等待执行的任务

5任务拒绝策略
当线程池的任务缓存队列已满而且线程池中的线程数目达到maximumPoolSize,若是还有任务到来就会采起任务拒绝策略,一般有如下四种策略:

ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。

ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,可是不抛出异常。

ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,而后从新尝试执行任务(重复此过程)

ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

6线程池的关闭
ThreadPoolExecutor提供了两个方法,用于线程池的关闭,分别是shutdown()和shutdownNow(),其中:

shutdown():不会当即终止线程池,而是要等全部任务缓存队列中的任务都执行完后才终止,但不再会接受新的任务

shutdownNow():当即终止线程池,并尝试打断正在执行的任务,而且清空任务缓存队列,返回还没有执行的任务
7线程池容量的动态调整
ThreadPoolExecutor提供了动态调整线程池容量大小的方法:setCorePoolSize()和setMaximumPoolSize(),

setCorePoolSize:设置核心池大小

setMaximumPoolSize:设置线程池最大能建立的线程数目大小

当上述参数从小变大时,ThreadPoolExecutor进行线程赋值,还可能当即建立新的线程来执行任务。
2020腾讯面试题!附答案

若是是不采用是这个那就在队列中的线程是不可能出队列的,就是若是是的非公平的锁的话那就永远不能出队列。那可能能执行不到该线程。

JVM调优(不太会)
Xms2g:初始化推大小为 2g;

-Xmx2g:堆最大内存为 2g;

-XX:NewRatio=4:设置年轻的和老年代的内存比例为 1:4;

-XX:SurvivorRatio=8:设置新生代 Eden 和 Survivor 比例为 8:2;

–XX:+UseParNewGC:指定使用 ParNew + Serial Old 垃圾回收器组合;

-XX:+UseParallelOldGC:指定使用 ParNew + ParNew Old 垃圾回收器组合;

-XX:+UseConcMarkSweepGC:指定使用 CMS + Serial Old 垃圾回收器组合;

-XX:+PrintGC:开启打印 gc 信息;

-XX:+PrintGCDetails:打印 gc 详细信息。

如何判断对象是否应该被回收(引用计数法,可达性分析)

root根包括哪些:对象头

CMS回收过程,优缺点

并行收集垃圾
2020腾讯面试题!附答案

初始标记:只是标记一下 GC Roots 能直接关联的对象,速度很快,仍然须要暂停全部的工做线程。

并发标记:进行 GC Roots 跟踪的过程,和用户线程一块儿工做,不须要暂停工做线程。

从新标记:为了修正在并发标记期间,因用户程序继续运行而致使标记产生变更的那一部分对象的标记记录,仍然须要暂停全部的工做线程。

并发清除:清除 GC Roots 不可达对象,和用户线程一块儿工做,不须要暂停工做线程。因为耗时最长的并发标记和并发清除过程当中,垃圾收集线程能够和用户如今一块儿并发工做, 因此整体上来看CMS 收集器的内存回收和用户线程是一块儿并发地执行:

G1回收过程
2020腾讯面试题!附答案

类加载过程(加载,验证,准备,解析,初始化)
2020腾讯面试题!附答案

双亲委派优势
2020腾讯面试题!附答案

=

七层模型

物理层 数据链路层 网络层 传输层 表示层 应用层 会话层
2020腾讯面试题!附答案

四次挥手过程(中间状态也要答)
HttpTCP 在传输以前会进行三次沟通,通常称为“三次握手”,传完数据断开的时候要进行四次沟通,通常称为“四次挥手”。(就是Http的链接和断开的模式)
2020腾讯面试题!附答案

第一次握手:主机 A 发送位码为 syn=1,随机产生 seq number=1234567 的数据包到服务器,主机 B由 SYN=1 知道, A 要求创建联机;

第 二 次 握 手 : 主 机 B 收 到 请 求 后 要 确 认 联 机 信 息 , 向 A 发 送 ack number=( 主 机 A 的seq+1),syn=1,ack=1,随机产生 seq=7654321 的包

第三次握手: 主机 A 收到后检查 ack number 是否正确,即第一次发送的 seq number+1,以及位码ack 是否为 1,若正确, 主机 A 会再发送 ack number=(主机 B 的 seq+1),ack=1,主机 B 收到后确认。

四次挥手:
2020腾讯面试题!附答案

TCP 创建链接要进行三次握手,而断开链接要进行四次。这是因为 TCP 的半关闭形成的。由于 TCP 链接是全双工的(即数据可在两个方向上同时传递)因此进行关闭时每一个方向上都要单独进行关闭。这个单方向的关闭就叫半关闭。当一方完成它的数据发送任务,就发送一个 FIN 来向另外一方通告将要终止这个方向的链接。

1关闭客户端到服务器的链接:首先客户端 A 发送一个 FIN,用来关闭客户到服务器的数据传送,而后等待服务器的确认。其中终止标志位 FIN=1,序列号 seq=u

2服务器收到这个 FIN,它发回一个 ACK,确认号 ack 为收到的序号加 1。

3关闭服务器到客户端的链接:也是发送一个 FIN 给客户端。

4客户段收到 FIN 后,并发回一个 ACK 报文确认,并将确认序号 seq 设置为收到序号加 1。

首先进行关闭的一方将执行主动关闭,而另外一方执行被动关闭。

为何TCP能保证不丢失

(滑动窗口,拥塞控制)

HTTP和HTTPS的区别
2020腾讯面试题!附答案

GET和POST区别

安全性:get 不安全 post 相对安全

传输的大小:get的传输较小 POST的传输较大

数据的来源范式Get是从服务器上得到数据,而Post则是向服务器传递数据的。

mysql全家桶又来了,索引数据结构
采用是B+树,B+的设计底层数据结构和相关的索引的知识。

为何用B+树而不用hash和B-Tree
二叉树(可能出现所有在左边和右边的数据)——>AVL(平衡二叉树数据大量的时候平衡的时间太多,)——>B Tree(多路平衡查找树)(数据表中的数据都是存储在页中的,因此一个页中能存储多少行数据呢指针少的状况下要保存大量数据,只能增长树的高度,致使IO操做变多,查询性能变低)——>B+ Tree的一个演变的过程来进行分析,为何使用B+ Tree的?B+ Tree,都放在了叶子节点上。提升了检索的效率。预读原理,由于B+ Tree无 data 域,其实就是由于没有date域了,可是每次IO的页的大小是固定的,每次IO读取若干个块块中包含的Key域的值确定更多啊,B+树单次磁盘IO的信息量大于B树,从这点来看B+树相对B树磁盘 IO 次数少。利用了磁盘预读原理,将一个节点的大小设为等于一个页,这样每一个节点只须要一次I/O就能够彻底载入。一、B+Tree中由于数据都在叶子节点,因此每次查询的时间复杂度是固定的,由于稳定性保证了二、并且叶子节点之间都是链表的结构,因此B+Tree也是能够支持范围查询的,而B树每一个节点 key 和 data 在一块儿,则没法区间查找。

InooDB和MyISAM的区别(事务,汇集索引,锁的粒度等)
2020腾讯面试题!附答案

回表,联合索引查询会不会用到索引系列问题
下面咱们来假设一种状况,一个表有三个字段 ID ,name ,age,我将ID设置成主键索引,name设成辅助索引。而后来看一下下面的sql:

1.select * from t where id='5';

2.select * from t where name='张三';

两个很简单的Sql,第一个sql不用说,直接经过主键索引,从树上直接能够获得结果,那第二个sql:首先name,mysql并不能获得全部列的信息(也就是 ),他只能获得主键ID,而后他会根据ID在进行二次查询,这就引起了--回表问题。这就是为啥不能使用 的缘由。那么怎么解决那:第一不要写*,第二利用组合索引,也就是说你根据业务实际须要,将须要的字段造成组合索引。

因此是会用到的索引的。

最左匹配是什么意思,联合索引创建索引过程
在Mysql创建多列索引(联合索引)有最左前缀的原则,即最左优先。假设咱们有两列a,b,a和b是联合索引,他的顺序是a,b,咱们在where语句中调用a=? and b=?的时候就会走联合索引,若是调用where a = ?的时候也会走索引,可是当咱们使用where b = ?的时候就不会走这个联合索引。

成因:mysql建立复合索引的规则是首先会对复合索引的最左边,也就是索引中的第一个字段进行排序,在第一个字段排序的基础上,在对索引上第二个字段进行排序,其实就像是实现相似order by 字段1,字段2这样的排序规则,那么第一个字段是绝对有序的,而第二个字段就是无序的了,所以通常状况下直接只用第二个字段判断是用不到索引的,这就是为何mysql要强调联合索引最左匹配原则的缘由。

独占所,共享锁,乐观锁讲一下
写锁是独占锁 ,在这个期间是不容许的任何线程来操做对象的。 读锁就是共享锁,可使让其余线程的来读取的,可是不容许有修改。乐观锁是共享锁的一种,在经过乐观锁的时候获取对象的时候先比较一下乐观锁的版本号。若是版本号是正确的,那就能够获取对象。若是是版本不对的话。那就是不容许修改的。

mysql分库分表?
垂直拆分
垂直分库是根据数据库里面的数据表的相关性进行拆分,好比:一个数据库里面既存在用户数据,又存在订单数据,那么垂直拆分能够把用户数据放到用户库、把订单数据放到订单库。垂直分表是对数据表进行垂直拆分的一种方式,常见的是把一个多字段的大表按经常使用字段和很是用字段进行拆分,每一个表里面的数据记录数通常状况下是相同的,只是字段不同,使用主键关联

垂直拆分的优势是:
可使得行数据变小,一个数据块(Block)就能存放更多的数据,在查询时就会减小I/O次数(每次查询时读取的Block 就少)

能够达到最大化利用Cache的目的,具体在垂直拆分的时候能够将不常变的字段放一块儿,将常常改变的放一块儿

数据维护简单

垂直拆分缺点是:
主键出现冗余,须要管理冗余列

会引发表链接JOIN操做(增长CPU开销)能够经过在业务服务器上进行join减小数据库压力

依然存在单表数据量过大的问题(须要水平拆分)

事务处理复杂

水平拆分
水平拆分是经过某种策略将数据分片来存储,分库内分表和分库两部分,每片数据会分散到不一样的MySQL表或库,达到分布式的效果,可以支持很是大的数据量。前面的表分区本质上也是一种特殊的库内分表 库内分表,仅仅是单纯的解决了单一表数据过大的问题,因为没有把表的数据分布到不一样的机器上,所以对于减轻MySQL服务器的压力来讲,并无太大的做用,你们仍是竞争同一个物理机上的IO、CPU、网络,这个就要经过分库来解决

水平拆分的优势是:
不存在单库大数据和高并发的性能瓶颈

应用端改造较少

提升了系统的稳定性和负载能力

缺点是:
分片事务一致性难以解决

跨节点Join性能差,逻辑复杂

数据屡次扩展难度跟维护量极大

分片原则
能不分就不分,参考单表优化

分片数量尽可能少,分片尽可能均匀分布在多个数据结点上,由于一个查询SQL跨分片越多,则整体性能越差,虽然要好于全部数据在一个分片的结果,在必要的时候进行扩容,增长分片数量

分片规则须要慎重选择作好提早规划,分片规则的选择,须要考虑数据的增加模式,数据的访问模式,分片关联性问题,以及分片扩容问题,最近的分片策略为范围分片,枚举分片,一致性Hash分片,这几种分片都有利于扩容

尽可能不要在一个事务中的SQL跨越多个分片,分布式事务一直是个很差处理的问题

查询条件尽可能优化,尽可能避免Select * 的方式,大量数据结果集下,会消耗大量带宽和CPU资源,查询尽可能避免返回大量结果集,而且尽可能为频繁使用的查询语句创建索引。

经过数据冗余和表分区赖下降跨库Join的可能。

这里特别强调一下分片规则的选择问题,若是某个表的数据有明显的时间特征,好比订单、交易记录等,则他们一般比较合适用时间范围分片,由于具备时效性的数据,咱们每每关注其近期的数据,查询条件中每每带有时间字段进行过滤,比较好的方案是,当前活跃的数据,采用跨度比较短的时间段进行分片,而历史性的数据,则采用比较长的跨度存储。

整体上来讲,分片的选择是取决于最频繁的查询SQL的条件,由于不带任何Where语句的查询SQL,会遍历全部的分片,性能相对最差,所以这种SQL越多,对系统的影响越大,因此咱们要尽可能避免这种SQL的产生。

sql优化
1字段的优化

2查询的优化

3索引的优化

4读写分离

5分库分表的操做

6数据库集群的操做

线程和进程概念(共享哪些区域)
1.堆

几乎全部对象实例被分配到这里,也是垃圾收集器管理的主要区域。Java堆能够被分为新生代和老生代。进一步划分,则有Eden空间、From Survivor空间、To Survivor空间等。不管如何划分,都是为了更好地回收内存、更快的分配内存。

方法区
方法区因为存储虚拟机加载的类的信息、常量、静态变量、JIT编译后的代码等。

虚拟内存讲一下(分页)

synchronized和Lock的区别

一个是经过指令集来实现锁住的对象的头来实现加锁的。

一个是经过设置一个标志位置来锁住独享的。

volatile的做用

JMM内存模型和缓存一致性协议还有就是的一个是保持可见性的

算法题:存储有[0,n)的数组,数组长度为len。只能交换数组里n和0的位置进行排序

/查询学生表中姓名、学号,并以学号降序排序/
select name,StuID from Students_information order by StuID desc /*order by 以什么排序,默认为升序,desc是降序/

/查询学生表中前5名学生的姓名,学号,并以学号升序排列/
select top 5 name,StuID from Students_information order by StuID /order by 默认为升序/
二面:
项目问题10分钟,问到了Hash冲突

利用是数组+链表来解决hash冲突

synchronized底层实现(markWord,entrySet,waitSet)
经过锁住对象的头部来实现对对象加锁,synchronize的关键字在之前是使用的指令来实现的

他属于独占式的悲观锁,同时属于可重入锁。代码块同步是使用monitorenter和monitorexit指令实现的。monitorenter指令是在编译后插入到同步代码块的开始位置,而monitorexit是插入到方法结束处和异常处,JVM要保证每一个monitorenter必须有对应的monitorexit与之配对任何对象都有一个monitor与之关联,当且一个monitor被持有后,它将处于锁定状态。

在Java中,锁共有4种状态,级别从低到高依次为:无状态锁,偏向锁,轻量级锁和重量级锁状态,这几个状态会随着竞争状况逐渐升级。锁能够升级但不能降级。?经过一个标志位来判断 两个位置00表示的4种锁

AQS底层实现(非公平锁,公平锁)
底层采用的是双链表的来实现了的,公共锁的定义是全部的对象在获取锁的时候都是须要进入队列的。非公平锁是在对象获取锁的时候是采用是首先查看锁是否为空,若是是空的话,那就能够对获取,若是是有对象持有的话,那就进入队列进行排队。

Spring ICO,AOP介绍
SpringIOC是spring对提供了对类的全生命周期的管理的一种思想,利用反射机制来实现的对Bean的实例化产生和建立和销毁这样的机制。来实现对类对的属性的控制,这个过程当中Bean实例和生命周期是SpringIOC中最重要的。Spring的Bean产生详细请见其余。

SpringAOP是一种切向编程的思想。在传统的过程时候因为是在传统的架构中都是垂直的流程体系。可是在这个过程当中常常产生一些横向问题,好比log日志记录,权限验证,事务处理,性能检查的问题,为了遵循软件的开闭原则。就是对原来不修改进而扩展原累的方法和功能。SpringAOP就是实现了这样一种思想。经过对原方法和类在不修改代码的状况下而进行了类的加强的方式。

Spring用到了什么设计模式
工厂模式:BeanFactory就是简单工厂模式的体现,用来建立对象的实例;

单例模式:Bean默认为单例模式。

代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;

模板方法:用来解决代码重复的问题。好比. RestTemplate, JmsTemplate, JpaTemplate。

观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,全部依赖于它的对象都会获得通知被制动更新,如Spring中listener的实现–ApplicationListener。

单例为何加锁,volatile什么做用
单例模式中有一种是懒汉模式。这样的模式是会产生的线程安全的问题。volatile是让变量在多线程的状况下保持对其余线程的可见。

hashmap何时用到了红黑树
当链表的节点超过8个时候采用红黑树来实现存储。

介绍红黑树特色,为何不用AVL树
红黑树属于平衡二叉树。它不严格是由于它不是严格控制左、右子树高度或节点数之差小于等于1,但红黑树高度依然是平均log(n),且最坏状况高度不会超过2log(n)。红黑树的插入效率比AVL的数要高。

红黑树不追求"彻底平衡",即不像AVL那样要求节点的 |balFact| <= 1,它只要求部分达到平衡,可是提出了为节点增长颜色,红黑是用非严格的平衡来换取增删节点时候旋转次数的下降,任何不平衡都会在三次旋转以内解决,而AVL是严格平衡树,所以在增长或者删除节点的时候,根据不一样状况,旋转的次数比红黑树要多

算法题:一个链表:奇数序号升序,偶数序号降序,要求作这个链表的总体升序排序
private static ListNode[] splitList(ListNode head) {
ListNode cur = head;

ListNode head1 = null;
ListNode head2 = null;
ListNode cur1 = null;
ListNode cur2 = null;
int num = 1;

while (head != null) {
    if (num % 2 == 1) {
        if (cur1 != null) {
            cur1.next = head;
            cur1 = cur1.next;
        } else {
            cur1 = head;
            head1 = cur1;
        }
    } else {
        if (cur2 != null) {
            cur2.next = head;
            cur2 = cur2.next;
        } else {
            cur2 = head;
            head2 = cur2;
        }
    }

    head = head.next;
    num++;
}

cur1.next = null;
cur2.next = null;
ListNode[] heads = new ListNode[]{head1, head2};
return heads;

}

private static ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode cur = head;

while (cur != null) {
    ListNode next = cur.next;
    cur.next = pre;
    pre = cur;
    cur = next;
}

return pre;

}

private static ListNode mergeLists(ListNode head1, ListNode head2) {
if (head1 == null && head2 == null) {
return null;
}

if (head1 == null || head2 == null) {
    return head1 == null ? head2 : head1;
}

ListNode first = new ListNode(-1);
ListNode cur = first;

while (head1 != null && head2 != null) {
    if (head1.val < head2.val) {
        cur.next = head1;
        head1 = head1.next;
    } else {
        cur.next = head2;
        head2 = head2.next;
    }
}

cur.next = head1 == null ? head2 : head1;

return first.next;

}
三面:

介绍了两个项目

怎么解决超卖(答:redis + mysql乐观锁)

职业规划 + 想成为tech lead应该应该具有什么条件

如今有哪些offer

相关文章
相关标签/搜索