简历:第二章:技术亮点备战

2021-03-12 11:19:06 浏览数 (1)

个人觉得需要花费一个月时间精心准备,想要拿高薪就必须恶心自己。

面试回答通用套路:先介绍是什么,运行原理是什么样的,然后举例说明便于理解,最后结合案例分析优缺点,提出解决方案

熟练掌握常用的java集合以及多线程并发环境下集合类出现的并发修改异常。比如,写时复制,CAS,ABA,Volatilte等。

HashMap是Map的一个实现类,它是以键值对存储数据的,Key-Value都是Map.Entry中的属性。当我们向HashMap中存放一个元素(k1,v1),先根据k1的hashCode方法来决定在数组中存放的位置。如果这个位置没有其它元素,将(k1,v1)直接放入一个Node类型的数组中,当元素加到12的时候,底层会进行扩容,扩容为原来的2倍。如果该位置已经有其它元素(k2,v2),那就调用k1的equals方法和k2进行比较二个元素是否相同,如果结果为true,说明二个元素是一样的,用v1替换v2,如果返回值为false,二个元素不一样,就用链表的形式将(k1,v1)存放。不过当链表中的数据较多时,查询的效率会下降,所以在JDK1.8版本后做了一个升级,HashMap存储数据结构链表长度超过8且数组长度大于64时数据结构,会将链表替换成红黑树才会树化时,会将链表替换成红黑树,来提高查找效率。因为对于搜索,插入,删除操作多的情况下,使用红黑树的效率要高一些。因为红黑树是一种特殊的二叉查找树,二叉查找树所有节点的左子树都小于该节点,所有节点的右子树都大于该节点,就可以通过大小比较关系来进行快速的检索。在红黑树上插入或者删除一个节点之后,红黑树就发生了变化,但它不再是一颗红黑树时,可以通过左旋和右旋,保证每次插入最多只需要三次旋转就能达到平衡,因为红黑树强制约束了从根到叶子的最长的路径不多于最短的路径的两倍长,插入、删除和查找某个值的最坏情况时间都要求与树的高度成比例,这个在高度上的理论上限允许红黑树在最坏情况下都是高效的。

HashMap实际使用过程中会出现一些线程安全问题,在JDK1.7中,当并发执行扩容操作时会造成环形链和数据丢失的情况,开多个线程不断进行put操作,rehash的时候,旧链表迁移新链表的时候,如果在新表的数组索引位置相同,则链表元素会倒置(就是因为头插) 所以最后的结果打乱了插入的顺序,就可能发生环形链和数据丢失的问题,引起死循环,导致CPU利用率接近100%。在jdk1.8中对HashMap进行了优化,发生hash碰撞,不再采用头插法方式,而是直接插入链表尾部,因此不会出现环形链表的情况,但是在多线程环境下,会发生数据覆盖的情况,如果没有hash碰撞的时候,它会直接插入元素。如果线程A和线程B同时进行put操作,刚好这两条不同的数据hash值一样,并且该位置数据为null,线程A进入后还未进行数据插入时挂起,而线程B正常执行,从而正常插入数据,然后线程A获取CPU时间片,此时线程A不用再进行hash判断了,线程A会把线程B插入的数据给覆盖,导致数据发生覆盖的情况,发生线程不安全。

除此之外还有故障现象:java.util.ConcurrentModificationException并发修改异常。导致原因:并发争取修改导致,一个线程正在写,一个线程过来争抢,导致线程写的过程被其他线程打断,导致数据不一致。

第一种解决方案使用HashTable:

HashTable是线程安全的,只不过实现代价却太大了,简单粗暴,get/put所有相关操作都是synchronized的,这相当于给整个哈希表加了一把大锁。多线程访问时候,只要有一个线程访问或操作该对象,那其他线程只能阻塞,相当于将所有的操作串行化,在竞争激烈的并发场景中性能就会非常差。

第二种解决方案使用工具类,线程同步:Map<String,String> hashMap = Collections.synchronizedMap(new HashMap<>());

和Hashtable一样,实现上在操作HashMap时自动添加了synchronized来实现线程同步,都对整个map进行同步,在性能以及安全性方面不如ConcurrentHashMap。

第三种解决方案使用写时复制:CopyOnWrite:往一个容器里面加元素的时候,不直接往当前容器添加,而是先将当前容器的元素复制出来放到一个新的容器中,然后新的元素添加元素,添加完之后,再将原来容器的引用指向新的容器,这样就可以对它进行并发的毒,不需要加锁,因为当前容器不添加任何元素。利用了读写分离的思想,读和写是不同的容器。

会有内存占用问题,在复制的时候只是复制容器里的引用,只是在写的时候会创建新对象添加到新容器里,而旧容器的对象还在使用,所以有两份对象内存。

会有数据一致性问题,CopyOnWrite容器只能保证数据的最终一致性,不能保证数据的实时一致性。

第四种解决方案:使用ConcurrentHashMap:

为了应对hashmap在并发环境下不安全问题可以使用,ConcurrentHashMap大量的利用了volatile,CAS等技术来减少锁竞争对于性能的影响。在JDK1.7版本中ConcurrentHashMap避免了对全局加锁,改成了局部加锁(分段锁),分段锁技术,将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问,能够实现真正的并发访问。不过这种结构的带来的副作用是Hash的过程要比普通的HashMap要长。

所以在JDK1.8版本中CurrentHashMap内部中的value使用volatile修饰,保证并发的可见性以及禁止指令重排,只不过volatile不保证原子性,使用为了确保原子性,采用CAS(比较交换)这种乐观锁来解决。CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。如果内存地址里面的值和A的值是一样的,那么就将内存里面的值更新成B。CAS是通过无限循环来获取数据的,若果在第一轮循环中,a线程获取地址里面的值被b线程修改了,那么a线程需要自旋,到下次循环才有可能机会执行。

volatile有三个特性:可见性,不保证原子性,禁止指令重排。

可见性:线程1从主内存中拿数据1到自己的线程工作空间进行操作(假设是加1)这个时候数据1已经改为数据2了,将数据2写回主内存时通知其他线程(线程2,线程3),主内存中的数据1已改为数据2了,让其他线程重新拿新的数据(数据2)。

不保证原子性:线程1从主内存中拿了一个值为1的数据到自己的工作空间里面进行加1的操作,值变为2,写回主内存,然后还没有来得及通知其他线程,线程1就被线程2抢占了,CPU分配,线程1被挂起,线程2还是拿着原来主内存中的数据值为1进行加1,值变成2,写回主内存,将主内存值为2的替换成2,这时线程1的通知到了,线程2重新去主内存拿值为2的数据。

禁止指令重排:首先指令重排是程序执行的时候不总是从上往下执行的,就像高考答题,可以先做容易的题目再做难的,这时做题的顺序就不是从上往下了。禁止指令重排就杜绝了这种情况。

熟练掌握线程池底层实现原理并可根据实际业务场景配置合理的线程数以及拒绝策略。

线程池就是控制运行的线程数量,处理过程中将任务放到队列,然后在线程创建后启动这些任务,如果线程数量超出了最大数量就排队等候,等其他线程执行完毕再从队列中取出任务执行。

线程池相当于银行网点,常驻核心数相当于今日当值窗口,线程池能够同时执行的最大线程数相当于银行所有的窗口,任务队列相当于银行的候客区,当今日当值窗口满了,多出来的客户去候客区等待,当候客区满了,银行加开窗口,候客区先来的客户去加班窗口,当银行所有的窗口满了,其他客户在候客区等待,同时拒绝其他客户进入银行。当用户少了,加班的窗口等待时间(相当于多余线程存活的时间)(等待时间的单位相当于unit参数)假设超过一个小时还是没有人来,就取消加班的窗口。

底层在创建线程池的时候有七个参数:核心线程数,同时执行的最大线程数,多余线程存活时间,单位时间秒,任务队列,默认线程工厂,拒绝策略

corePoolSize:核心线程数,如何合理的配置核心线程数?

对于CPU密集型任务,由于CPU密集型任务的性质,导致CPU的使用率很高,如果线程池中的核心线程数量过多,会增加上下文切换的次数,带来额外的开销。因此,考虑到CPU密集型任务因为某些原因而暂停,这个时候有额外的线程能确保CPU这个时刻不会浪费,还可以增加一个CPU上下文切换。一般情况下:线程池的核心线程数量等于CPU核心数 1。例如需要大量的计算,视频渲染啊,仿真啊之类的。这个时候CPU就卯足了劲在运行,这个时候切换线程,反而浪费了切换的时间,效率不高。打个比方,你的大脑是CPU,你本来就在一本心思地写作业,多线程这时候就是要你写会作业,然后立刻敲一会代码,然后在P个图,然后在看个视频,然后再切换回作业。emmmm,过程中你还需要切换(收起来作业,拿出电脑,打开VS…)那你的作业怕是要写到挂科。这个时候你就该一门心思地写作业。

对于I/O密集型任务,由于I/O密集型任务CPU使用率并不是很高,可以让CPU在等待I/O操作的时去处理别的任务,充分利用CPU。一般情况下:线程的核心线程数等于2*CPU核心数。例如你需要陪小姐姐或者小哥哥聊天,还需要下载一个VS,还需要看博客。打个比方,小姐姐给你发消息了,回一下她,然后呢?她给你回消息肯定需要时间,这个时候你就可以搜索VS的网站,先下安装包,然后一看,哎呦,她还没给你回消息,然后看会自己的博客。小姐姐终于回你了,你回一下她,接着看我的博客,这就是类似于IO密集型。你可以在不同的“不烧脑”的工作之间切换,来达到更高的效率。而不是小姐姐不回我的信息,我就干等,啥都不干,就等,这个效率可想而知,也许,小姐姐根本就不会回复你。

对于混合型任务,由于包含2种类型的任务,故混合型任务的线程数与线程时间有关。在某种特定的情况下还可以将任务分为I/O密集型任务和CPU密集型任务,分别让不同的线程池去处理。一般情况下:线程池的核心线程数=(线程等待时间/线程CPU时间 1)*CPU核心数;

并发高、业务执行时间长,解决这种类型任务的关键不在于线程池而在于整体架构的设计,看看这些业务里面某些数据是否能做缓存是第一步,我们的项目使用的时redis作为缓存(这类非关系型数据库还是挺好的)。增加服务器是第二步(一般政府项目的首先,因为不用对项目技术做大改动,求一个稳,但前提是资金充足),至于线程池的设置,设置参考 2 。最后,业务执行时间长的问题,也可能需要分析一下,看看能不能使用中间件(任务时间过长的可以考虑拆分逻辑放入队列等操作)对任务进行拆分和解耦。

maximumPoolsize:同时执行的最大线程数

keepAliveTime:多余线程存活时间,当前线程池数量超过核心线程数时,当前空闲时间达到多余线程存活时间的值的时候,多余空闲线程会被销毁到只剩核心线程数为止

unit:多余线程存活时间的单位

workQueue:任务队列,被提交但尚未被执行的任务

threadFactory:生成线程池的线程工厂

handler:拒绝策略,当队列满了并且工作线程数量大于线程池的最大线程数时,提供拒绝策略。

第一种拒绝策略:AbortPolicy:超出最大线程数,直接抛出RejectedExecutionException异常阻止系统正常运行。可以感知到任务被拒绝了,于是你便可以根据业务逻辑选择重试或者放弃提交等策略。

第二种拒绝策略:该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者,相当于当线程池无能力处理当前任务时,会将这个任务的执行权交予提交任务的线程来执行,也就是谁提交谁负责,从而降低新任务的流量。(谁调用了你,到达最大线程数时,你回去找调用你的人,然后听从调用你的人安排)(超出的我们能办的给你办,不能办的给你回退 )这样的话提交的任务就不会被丢弃而造成业务损失,如果任务比较耗时,那么这段时间内提交任务的线程也会处于忙碌状态而无法继续提交任务,这样也就减缓了任务的提交速度,这相当于一个负反馈,也有利于线程池中的线程来消化任务。这种策略算是最完善的相对于其他三个。

第三拒绝策略:DiscardOldestPolicy:抛弃队列中等待最久的任务,也就是它丢弃的是队列中的头节点,然后把当前任务加入队列中尝试再次提交当前任务

第四种拒绝策略:DiscardPolicy:直接丢弃任务,不予任何处理也不抛异常,当任务提交时直接将刚提交的任务丢弃,而且不会给与任何提示通知。

在实际使用的时候,选择线程池的时候尽量不用JDK提供的三种常见的创建方式,因为它的底层队列是Linked这个接近于无界,非常大,这样会堆积大量的请求,从而导致OOM,阿里巴巴开发手册推荐我们使用ThreadPoolExecutor去创建线程池。

熟练掌握JUC并发包,比如:循环栅栏,信号灯,倒计时器等,aba,cas,aqs,unsafe,volatile,sync,常见的各种lock,oom如何定位问题,cpu过高如何定位,top,jps,jstack,jmap,mesi协议

CountDownLatch倒计时器:让一些线程阻塞直到另一些线程完成一系统操作后才被唤醒。一个 CountDownLatch 用给定的计数初始化。await() 方法阻塞,直到由于countDown() 方法的调用而导致当前计数达到零,之后所有等待线程被释放,并且任何后续的 await() 调用立即返回。 这是一个一次性的现象 - 计数无法重置。

举个例子:我们的API接口响应时间被要求在200ms以内,但是如果一个接口内部依赖多个三方/外部服务,那串行调用接口的响应时间必然很久,所以可使用内部服务并行调用进行优化。

假设接口内部依赖了10个外部服务,创建CountDownLatch实例,计数数量为10,有10个线程来完成任务,等待在CountDownLatch上的线程执行完才能继续执行那个响应时间较快的接口。latch.countDown();方法作用是通知CountDownLatch有一个线程已经准备完毕,倒计数器可以减一了。latch.await()方法要求主线程等待所有10个检查任务全部准备好才一起并行执行。

一种典型的场景就是火箭发射。在火箭发射前,为了保证万无一失,往往还要进行各项设备、仪器的检测。只有等到所有的检查完毕后,引擎才能点火。那么在检测环节当然是多个检测项可以同时进行的

Semaphore信号灯:多个共享资源互斥使用,控制线程并发数量,多个线程抢多个资源。

1、Semaphore信号量作为一种流控手段,可以对特定资源的允许同时访问的操作数量进行控制,例如池化技术(连接池)中的并发数,有界阻塞容器的容量等。

2、Semaphore中包含初始化时固定个数的许可,在进行操作的时候,需要先acquire获取到许可,才可以继续执行任务,如果获取失败,则进入阻塞;处理完成之后需要release释放许可。

3、acquire与release之间的关系:在实现中不包含真正的许可对象,并且Semaphore也不会将许可与线程关联起来,因此在一个线程中获得的许可可以在另一个线程中释放。可以将acquire操作视为是消费一个许可,而release操作是创建一个许可,Semaphore并不受限于它在创建时的初始许可数量。也就是说acquire与release并没有强制的一对一关系,release一次就相当于新增一个许可,许可的数量可能会由于没有与acquire操作一对一而导致超出初始化时设置的许可个数。 举例,有六台车抢三个停车位。

CyclicBarrier循环栅栏:当多个线程一起执行任务是,一个线程没有完成任务,其他线程都必须进入等待状态,等待这个线程完成任务后,才能再执行其他任务。强调相互等待,一个线程不完成,其他线程全部等待。

创建CyclicBarrier时,它默认的构造方法是 CyclicBarrier(int parties),其参数表示屏障拦截的线程数量。调用await方法的线程告诉CyclicBarrier自己已经到达同步点,然后当前线程被阻塞。

例如:一个公司去团建,需要大家全部集合完毕后,才能出发,有一个人员不到,全员都得等待。它的作用就是会让所有线程都等待完成后才会继续下一步行动。

CAS:https://liaozhiwei.blog.csdn.net/article/details/97611037

volatile:https://liaozhiwei.blog.csdn.net/article/details/97611028

从ReentrantLock的实现看AQS的原理及应用:https://tech.meituan.com/2019/12/05/aqs-theory-and-apply.html

unsafe:https://www.jianshu.com/p/db8dce09232d

synchronized 关键字:https://www.cnblogs.com/admol/p/13994297.html

各种锁:https://liaozhiwei.blog.csdn.net/article/details/106908803

oom如何定位问题:https://www.cnblogs.com/lujiango/p/9650927.html

top,jps,jstack,jmap:https://liaozhiwei.blog.csdn.net/article/details/107030159

cpu过高如何定位:https://jishuin.proginn.com/p/763bfbd282b6

MESI协议:https://www.cnblogs.com/itqczzz/p/12670782.html

熟悉掌握Redis数据结构的使用场景,熟悉Redis缓存高并发的使用场景。比如,单线程模型,aof,rdb,rewrite,主从,cluster,哪些类型,击穿、穿透、雪崩、数据一致性,一致性hash,布隆过滤器的原理,底层数据结构sds和跳表

内容太多,分章节了,顺便偷个懒引用一下其他大佬的文章,这些文章算是我精挑细选的,你想要成为高级开发,这些东西必须要吃到肚子里还能讲出来才行,当然还不止这些哈。

Redis五大数据结构应用场景落地:https://liaozhiwei.blog.csdn.net/article/details/114301491

Redis的五大数据类型底层实现原理:https://www.cnblogs.com/ysocean/p/9102811.html#_label1

Redis的单线程和高性能:https://liaozhiwei.blog.csdn.net/article/details/113930507

Redis持久化机制与安全机制:https://liaozhiwei.blog.csdn.net/article/details/113932050

Redis缓存延时双删保证和MySQL的数据一致性:https://blog.csdn.net/qq_33589510/article/details/109531954

缓存穿透、缓存击穿、缓存雪崩:https://www.cnblogs.com/ysocean/p/12452023.html

过期删除策略和内存淘汰策略:https://www.cnblogs.com/ysocean/p/12422635.html

哨兵(Sentinel)模式详解:https://www.cnblogs.com/ysocean/p/12290364.html

热点缓存处理方案:https://www.cnblogs.com/thinkqin/articles/11955856.html

Redis布隆过滤器:https://www.cnblogs.com/ysocean/p/12594982.html

深入理解MySQL底层索引数据结构,B tree索引特点以及数据库事务的隔离级别,锁,主从

MySQL索引 B 树 数据库事务隔离级别: https://www.jianshu.com/p/a591b11c1b46

MySQL索引背后的数据结构及算法原理: http://blog.codinglabs.org/articles/theory-of-mysql-index.html

MySQL锁:https://blog.csdn.net/qq_40378034/article/details/90904573

MySQL主备、主从、读写分离:https://blog.csdn.net/qq_40378034/article/details/91125768

深入理解JVM底层原理,JMM内存模型,垃圾回收机制,GC算法,熟悉JVM各种垃圾回收器的使用以及核心参数调优,类加载过程,双亲委派,逃逸分析

JVM内存模型,算法,垃圾回收器,调优:https://liaozhiwei.blog.csdn.net/article/details/106630556

类加载过程:https://liaozhiwei.blog.csdn.net/article/details/107920767

逃逸分析:https://blog.csdn.net/hollis_chuang/article/details/80922794

Java对象结构与锁实现原理及MarkWord详解:https://blog.csdn.net/scdn_cp/article/details/86491792#comments

熟悉常见消息中间件的使用,解决过各种消息通讯场景的疑难问题。比如,重复消费,顺序消息,事务消息,高可用,消息丢失,挤压场景,整个消息发送消费的流程

mq如何保证高可用,解决重复消费、数据丢失问题和顺序性问题:https://www.jianshu.com/p/c833de561335

分布式事务:https://www.cnblogs.com/mayundalao/p/11798502.html

消息专题:https://www.cnblogs.com/jack1995/category/1469110.html

在项目中解决过各种分布式场景的技术难题,比如分布式锁,分布式事务。抢红包,高并发下单等常规的场景设计

分布式常见问题:https://www.cnblogs.com/xuwc/p/9139164.html

分布式锁,session,事务:https://www.yuque.com/baiqi-giihx/ldopha/hr6362

熟练掌握spring,spring mvc,mybatis,spring boot等开源框架,bean的生命周期,如何解决循环依赖,父子容器,还有boot的启动流程,事务实现原理,动态代理原理

解决spring循环依赖:https://blog.csdn.net/qq_36381855/article/details/79752689

bean的生命周期:https://liaozhiwei.blog.csdn.net/article/details/84391519

父子容器:http://www.tianshouzhi.com/api/tutorials/spring

Springboot启动流程:https://www.cnblogs.com/trgl/p/7353782.html

事务实现原理:https://www.zhihu.com/question/428589024/answer/1556584930

动态代理原理:https://www.cnblogs.com/gonjan-blog/p/6685611.html

深入理解spring could,zookeeper,dubbo等开源框架的底层架构。设计框架,负载均衡,spi机制,选举算法

SpringCould:

https://blog.csdn.net/forezp/article/details/70148833

https://blog.csdn.net/qq_41701956/article/details/83829539

zookeeper:

https://blog.csdn.net/u011414200/article/details/50248099?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-9&spm=1001.2101.3001.4242

https://liaozhiwei.blog.csdn.net/article/details/107029848

dubbo:

spi:https://blog.csdn.net/lzb348110175/article/details/98484451

负载均衡:https://www.jianshu.com/p/c08197641500

选举算法:https://www.cnblogs.com/sweet6/p/10574574.html

熟练掌握Linux常用命令,生产环境服务器变慢诊断,线上排查,性能评估。

故障排查:https://liaozhiwei.blog.csdn.net/article/details/107005583

Netty的话,零拷贝,bio,nio,aio,架构设计怎么样子的?

https://blog.csdn.net/qq_39311377/article/details/110699288

高频面试题:https://www.cnblogs.com/iwenwen/category/1485041.html

原文地址【阿里P6面经】

Java集合比如说HashMap和ConcurrentHashMap我觉得,你最好在平时能去耐心读一下源码,搜一搜相关的博客,最好能知道每个参数为什么设置成这么大?有什么好处?为什么?你会发现不少东西,网上也有很多视频可以去学。

JUC包,毫无疑问的,你得去学,哪怕你平时编程根本不去用,但是你得会,只得知道有这个东西,你至少得知道aba,cas,aqs,unsafe,volatile,sync,常见的各种lock,死锁,线程池参数和如何合理的去设置,你必须明白自旋,阻塞,死锁和它如何去定位,oom如何定位问题,cpu过高如何定位等基本的操作,你可以没有生产调试经验,但不代表你可以不会top,jps,jstack,jmap这些可能会问的东西。以及可能衍生的jmm模型和mesi协议等。

JVM毫无意外,大厂必须问,垃圾回收算法,垃圾收集器,jvm内存模型,每个区域用途,各种oom的种类,jvm调优经验,没有你也要做过,自己去设置启动参数,知道常见参数的含义,类加载过程,双亲委派,什么时候young gc,full gc,各种情况进入老年代的方式,你知道的越多越好,因为吹起来就越自信,举个例子,逃逸分析是什么?markword里面有什么?

Spring,最好能抽空看看源码,最起码bean的生命周期,如何解决循环依赖,父子容器,还有boot的启动流程,事务实现原理,动态代理原理等,你知道越多越好。

Dubbo,因为我用的是dubbo,而且我写了,这个也是高频,写了必须问的,他的设计框架,负载均衡,spi机制,一般顺势会提到zk,选举算法,分布式锁等,一些常见的dubbo问题可以去搜,网上的基本都有。可能会顺带去问cloud的问题,生产没用过不怕,你现在可以自己clone一个项目,最起码,互联娃,你得知道还有这个玩意儿,还有他集成了啥,比如rureka,hystrix,ribbon,feign,zuul这些常规的东西吧,他们做什么的?

Redis,必须会的,我这方便还算懂得多点,可以和面试官大战几个回合吧,应该不至于上来被打趴下,单线程模型,aof,rdb,rewrite,主从,cluster,哪些类型,不要再说常规的5个了,多说几个让你区别其他小哥,包含一些缓存常见的问题击穿、穿透、雪崩、数据一致性等,你必须会,不会基本没戏,一致性hash,布隆过滤器的原理,为此我还去了解了geohash的原理以及google s2的原理,底层数据结构sds和跳表等,你多学点,准没错。

Mysql,事务,锁,索引,b 树,主从这些你必须会

Mq ,我用的rocketmq,你得知道为什么用,重复消费,顺序消息,事务消息,高可用,消息丢失,挤压场景,整个消息发送消费的流程,读过源码更佳,更好吹

Netty的话,零拷贝,bio,nio,aio,架构设计怎么样子的?用过看过更好

算法,建议去刷题,我运气好,简单的算法让我碰到了,一些快排,堆排,二叉树相关的,链表反转,成环,环节点,跳楼梯等常规的简单算法建议刷刷,双指针,dp,递归这些还是多找找感觉,大数据内存有限的场景的统计,有时间一些middle可以去试试,手写红黑树你要是可以,那我估计算法你稳了。

网络,http,tcp,https,udp,7层网络协议等,最好结合自己理解,背,你都要背下来。

还有就是一些分布式事务实现,架构实现,比如抢红包,高并发下单等常规的场景设计,你来设计,你怎么去设计?多找一些大牛或者上网自己查,帮你看看有哪些漏洞,有那些解决方案?业界有哪些好的中间件?

基础性备战面试题:

HashMap底层原理,扩容机制,jdk8以后会使用红黑树优化?红黑树和二叉平衡树的区别,红黑树和B树,B 树的区别,Mysql二大引擎索引底层实现,HashMap在多线程环境中为何出错,ConcurrentHashMap底层实现,CAS,原子引用,ABA问题,volatile,如何解决HashMap出现的OOM问题?(WeakHashMap) 什么是Spring IOC,Spring AOP?应用场景有哪些?数据库事务隔离级别,MySQL默认的隔离级别、Spring如何实现事务、传播行为,分布式事务实现,分布式事务的四种解决方案,CAP,BASE Spring Bean的作用域和生命周期,Spring常用注解 23种设计模式 公平锁,非公平锁,可重入锁,递归锁,自旋锁,读写锁,悲观锁,乐观锁,行锁,表锁,死锁,分布式锁,线程同步锁,排它锁,共享锁,Synchronized,Lock等 幂等性实现,单点登录,金额篡改问题 JVM算法,堆溢出,栈溢出,JMM内存模型,垃圾回收机制,垃圾回收器,参数调优,双亲委派机制 线程池实现原理,七大核心参数,JUC并发包:信号灯,循环栅栏,倒计时器,集合类常见并发修改异常 SpringCould组件说七八个 Dubbo底层运行原理,支持的协议,支持的负载均衡策略,Zookeeper底层原理, zookeeper的选举机制,同步机制,mongo es的 分片,Spring MVC工作原理,Mybatis框架优点 Redis缓存数据结构,数据同步问题(双删策略),缓存雪崩,缓存穿透,热点缓存重构,缓存失效,哨兵机制,持久化,redis 淘汰机制 Sql优化,索引限制条件,存储过程限制条件 消息丢失,消息重复消费,消息顺序性,大规模消息积压问题,几种消息队列的区别 Linux常用命令,生产环境服务器变慢诊断,线上排查,性能评估。多线程、spring 扩展,数据库底层,各大互联网组件,底层机制,xx问题,如何排查。

技术亮点:

  • 熟练掌握常用的java集合以及多线程并发环境下集合类出现的并发修改异常。比如,写时复制,CAS,ABA,Volatilte等。
  • 熟练掌握线程池底层实现原理并可根据实际业务场景配置合理的线程数以及拒绝策略。
  • 熟练掌握JUC并发包,比如:循环栅栏,信号灯,倒计时器等。
  • 熟悉掌握Redis数据结构的使用场景,熟悉Redis缓存高并发的使用场景。比如,缓存雪崩,缓存穿透。
  • 深入理解MySQL底层索引数据结构,B tree索引特点以及数据库事务的隔离级别。 深入理解JVM底层原理,JMM内存模型,垃圾回收机制,GC算法,熟悉JVM各种垃圾回收器的使用以及核心参数调优。
  • 熟悉常见消息中间件的使用,解决过各种消息通讯场景的疑难问题。比如,消息丢失,消息重复消费。
  • 在项目中解决过各种分布式场景的技术难题,比如分布式锁,分布式事务。 熟练掌握spring,spring mvc,mybatis,spring boot等开源框架。 深入理解spring could,zookeeper,dubbo等开源框架的底层架构。 熟练掌握Linux常用命令,生产环境服务器变慢诊断,线上排查,性能评估。

0 人点赞