Java面试脑图思维导图_第1页
Java面试脑图思维导图_第2页
Java面试脑图思维导图_第3页
Java面试脑图思维导图_第4页
Java面试脑图思维导图_第5页
已阅读5页,还剩44页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Java面试•算法o排序算法▪比较排序•交换排序o冒泡排序o快速排序•插入排序o简单插入排序o希尔排序•选择排序o简单选择排序o堆排序•归并排序o二路归并排序o多路归并排序▪非比较排序•计数排序•桶排序•基数排序o查找算法▪二分查找▪顺序查找▪插值查找▪斐波那契查找▪树表查找▪分块查找▪•Springospring▪▪▪▪o优点▪▪哈希查找创建出来的对象作用域singleton•spring容器初始化时创建对象,设置lazy-init为true时,调用getBean时才会创建对象ototype•无论是否设置lazy-init,都只会在getBean时才会创建对象•为每个请求创建一个对象session•为每个session创建一个对象IOC•控制反转,别名依赖注入o由SpringIOC容器来负责对象的生命周期和对象之间的关系•InversionofcontrolAOP•定义o分散在各个方法中的重复代码提取出来,然后在程序编译或运行时,再将这些提取出来的代码应用到需要执行的地方。这种提取机制的方式。•动态代理方式oCGLIB代理▪类oJDK动态代理▪接口•JavaAOP框架oAspectJ▪区别•与SpringAOPoAspectJ▪编译时增强o基于字节码操作•SpringAOPo运行时增强o基于代理▪实用•日志•事务•权限•异常捕获•事务o传播机制▪REQUIRED•如果有事务,那么加入事务,没有的话新建一个(默认情况下)▪NOT_SUPPORTED•容器不为这个方法开启事务▪REQUIRES_NEW•不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务▪MANDATORY•必须在一个已有的事务中执行,否则抛出异常▪NEVER•必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)▪SUPPORTS•如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.•线程安全问题o发生在单例Bean中,当多个线程访问对象的非静态成员变量时,写操作会有线程安o解决▪ThreadLocal将变量保存起来•如何解决循环依赖的问题o通过三级缓存o构造器方式的循环依赖▪描述•A有构造器A(B),B有构造器B(A)▪无法解决•BeanCurrentlyInCreationExceptiono类属性的循环依赖▪描述▪基于引用传递▪创建A,B对象,并不立即设置其属性,统一放入一个Map中,设置属性时从•如何为我们创建对象o1.通过构造器创建对象o2.通过静态工厂创建o3.通过实例工厂创建•SpringMVCoSpringMVC的工作流程▪1.用户发送请求至前端控制器DispatcherServlet▪2.DispatcherServlet收到请求调用HandlerMapping处理器映射器▪3.处理器映射器找到具体的处理器(HandlerExecutionChain),返给DispatchServlet▪4.DispatcherServlet调用HandlerAdapter处理器适配器▪5.HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。▪6.Controller执行完成返回ModelAndView▪7.HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet▪8.DispatcherServlet将ModelAndView传给ViewReslover视图解析器▪9.ViewReslover解析后返回具体View▪10.DispatcherServlet根据View进行渲染视图▪11.DispatcherServlet响应用户•注解面试点oComponent注解与Bean注解的区别▪Component注解注解在类上,表示Spring将会为这个类创建bean▪Bean注解写在方法上,表示将该方法的返回值注册为一个spring应用上下文•Mysqlo隔离级别▪默认•可重复读o定义▪这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。o问题▪幻读•定义o幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,•解决oo模式会发现有新的“幻影”行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,MultiversionConcurrencyControl)机制解决了该问题▪快照读•读取的是记录的可见版本▪当前读o实现技术是mvcc▪防止幻读▪四种•ReadUncommitted(读取未提交内容)脏读o啥也不做(查询也不加锁)▪导致脏读,不可重复读,幻读o问题▪脏读•定义o所谓的脏读,其实就是读到了别的事务回滚前的脏数据▪。比如事务B执行过程中修改了,这样事务A就形成了脏o不可重复读o幻读▪ReadCommitted(读取提交内容)大部分数据库的默认隔离级别•一个事务只能看见已经提交事务所做的改变。这种隔离级别也称所谓的不可重复读(NonrepeatableRead)o使用快照,避免脏读,但避免不了不可重复读,幻读•问题o不可重复读▪当前事务先进行了一次数据读取,然后再次读取到的数据是别的事务修改成功的数据,导致两次读取到的数据不匹配,也就照应了不可重复读的语义▪发生在update,delete中o幻读▪RepeatableRead(可重复读)•定义o事务A在读到一条数据之后,此时事务B对该数据进行了修改并提交,那么事务A再读该数据,读到的还是原来的内容。•问题o读快照,不可修改,但避免不了新增删除,所以会产生幻读o幻读▪事务A首先根据条件索引得到N条数据,然后事务B改变了这N条数据之外的M条或者增添了M条符合事务A搜索条件的数据,导致事务A再次搜索发现有NM产生了幻读。▪insert中o解决▪MVCC与Next-Key▪Serializable(可串行化)•这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上表级共享锁。在这个级别,可能导致大量的超时现象和锁竞争。o两种事务隔离技术▪mvcc•mvcc的优势是不加锁,并发性高。缺点是不是实时数据。▪next-key•next-key的优势是获取实时数据,但是需要加锁•索引o数据结构▪B+tree•支持范围查询▪Hash•范围查找不支持▪创建时候可以选择创建什么数据类型的索引o为何用B+tree▪1.平衡二叉树的话数据一多,树高就高,增加IO次数,不利于查询▪2.为何不用B树o一张表最多可以建多少个索引▪一个表最多16个索引,最大索引长度256字节o问题▪虽然提高查询效率,牺牲插入,删除性能,会索引重排性较高,经常不发生变更的,经常查询的字段可以建立索引o比如电话号码▪索引失效•SQL语句写法oorounion•优化查询,调优oexplain执行计划,查看各方面的数据,或建索引oInnoDB表必须有主键?▪保证会有主键索引树的存在(因为数据存放在主键索引树上面),如果没有mysql会自己生成一个rowid作为自增的主键主键索引o为什么推荐使用整型的自增主键?▪方便查找比较▪新增数据的时候只需要在最后加入,不会大规模调整树结构•MyISAM与InnoDBo区别一▪MyISAM•表相关文件有三个o表数据与索引文件分开存储▪InnoDB•表相关文件有二个o索引与数据在同一个文件中(.idb)o区别二▪InnoDB•行级锁,支持事务,支持外键o适合高并发,重负荷▪MyISAM•表级锁,不支持事务o一般小项目可以使用•锁o全局锁o表锁o行锁o间隙锁o读写锁oInnoDB如何加锁•锁机制o共享/排它锁▪共享锁(ShareLocks,记为S锁),读取数据时加S锁•共享锁之间不互斥,简记为:读读可以并行▪排他锁(eXclusiveLocks,记为X锁),修改数据时加X锁•排他锁与任何锁互斥,简记为:写读,写写不可以并行o普通的select仍然可以读到数据(快照读)。o意向锁▪表级别的锁•InnoDB为了支持多粒度锁机制(multiplegranularitylocking),即允许行级锁与表级锁共存,而引入了意向锁(intentionlocks)。意向锁是指,未来的某个时刻,事务可能要加共享/排它锁了,先提前声明一个o记录锁▪记录锁,它封锁索引记录o间隙锁▪它封锁索引记录中的间隔,或者第一条索引记录之前的范围,又或者最后一条索引记录之后的范围。依然是o临键锁▪记录锁与间隙锁的组合,它的封锁范围,既包含索引记录,又包含索引区间。o插入意向锁o自增锁▪自增锁是一种特殊的表级别锁(table-levellock),专门针对事务插入AUTO_INCREMENT类型的列。•MVCCo多版本并发控制oMVCC只在RC和RR两个隔离级别下工作,其他两个隔离级别都和MVCC不兼容o目的▪为了实现数据库的并发控制而设计的一种协议•Rediso单线程▪有种情况严格意义上并不是单线程的•RDB时(命令:bgsave)o会Fork出一个子线程在后台备份数据,但还是可以操作rediso数据结构▪String字符串▪hash哈西▪set集合▪zset有序集合•SortSeto排行榜▪list列表▪还有三种特殊的•bitMap•Geo•HelperLogLog▪5.0•StreamoRedlock(红锁)o为何这么快▪Redis处理的这些请求都是计算型▪纯内存操作▪带有I/O多路复用功能o持久化▪1.RDB隔一段时间将内存快照写入硬盘▪2.AOP▪同时开启AOP数据全一点但是速度慢,RDB速度快但数据不全,一般应急都先用RDB先恢复大部分,然后使用AOF补全剩下的数据o集群(高可用)▪主备同步▪启动数据初始化▪rewriteoINCR命令(分布式锁)o分布式锁框架RedissionoSub/PuboBitMapo常见问题▪双写一致性面试o如何保证缓存与数据库的双写一致性?▪1.读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应。▪2.更新的时候,先更新数据库,然后再删除缓存。o最初的缓存不一致问题▪描述先更新数据库,再删除缓存。如果删除缓存失败了,那么会导致数据库中是新数据,缓存中是旧数据,数据就出现了不一致。▪解决•先删除缓存,再更新数据库。如果数据库更新失败了,那么数据库中是旧数据,缓存中是空的,那么数据不会不一致。因为读的时候缓存没有,所以去读了数据库中的旧数据,然后更o复杂的数据不一致问题分析▪描述•数据发生了变更,先删除了缓存,然后要去修改数据库,此时还没修改。一个请求过来,去读缓存,发现缓存空了,去查询数据库,查到了修改前的旧数据,放到了缓存中。随后数据变更的程序完成了数据库的修改。完了,数据库和缓存中的数据不一样了▪出现•每秒并发读是几万▪解决•<左侧灰色框>o简单也可以说▪双删操作处理•先删除缓存,再删除数据库,过1s后再删除缓存,防止删除数据库数据时,数据又写入缓存▪并发竞争▪大Key▪热点Key•缓存击穿▪缓存击穿•定义o缓存中的key一般设有过期时间,这个key在不停的扛着大并发,如果KEY过期了,恰在这个时候,有大量的并发请求访问这个key,则这些请求都会到达DB,导致DB瞬间压力过大,DB般是指热点数据。•解决o1.定时更新▪后台设置一个Job定时去刷新缓存的过期时间o2.检查更新▪将过期时间一并存入缓存,获取到后,判断是否小于一定时间,小于后,在更新过期时间,同1o3.分级缓存o4.加锁o5.简单的将热点key设置成永不过期▪缓存穿透•指有人用数据库中不存在的某个key访问,数据库中没有该key值,自然也不会写入缓存中,所有该请求的查询都会直接到数据库。如果对该key的并发访问量过大,则会压垮数据库。•解决o从请求出发▪对查出为空的key,也在缓存中建立keyvalue对,只是过期时间设的短一点,比如5minetes。o从数据库出发▪采用过滤器,把所有数据库中不可能存在的数据hash到一张大的bitmap中,如果key在数据库中不存o布隆过滤器▪对可能的key做一定的hash并存储在Bitmap里,不存在就过滤掉,存在的就按正常流程走▪缓存雪崩•定义o缓存雪崩,是指在某一个时间段,缓存集中过期失效。•解决o1.分散缓存过期时间▪如果是热点key的话就设置永不过期•致命的缓存雪崩,是缓存服务器某个节点宕机或断网o对数据库服务器造成的压力是不可预知的,很有可能瞬间就把o使用场景▪不适合•数据量太大、数据访问频率非常低的业务都不适合使用Redis。▪例子•SortSeto排行榜•计数器/限速器o点赞;收藏数;请求限流•好友关系o集合,并集,交集•简单消息队列o除了Redis自身的发布/订阅模式,我们也可以利用List来实现一个队列机制靠,但是步解耦•Session共享•访问的uv统计oHelperLoglogo网络层使用epoll解决高并发问题•RPC•Docker•微服务•SpringCloudoEureka▪服务注册流程oZuul▪网关ofeighohytrix▪熔断器•判断什么时候回熔断oribbon▪负载均衡•负载均衡的策略有多少种o轮询o权重•Dubboo调用链路•Kafka•RabbitMQoVhost▪内部有属于自己的channel,queue,exhange▪作用•应用隔离o消息基于什么传输▪信道•信道是建立在真实的TCP连接内的虚拟连接,且每条TCP连接上的信道数量没有限制▪为何不基于TCP•TCP连接的创建和销毁开销较大,且并发数受系统资源限制,会造成性能瓶颈o消息如何分发▪若该队列至少有一个消费者订阅,消息将以循环(round-robin)的方式发送o名词▪Publisher▪routingKey▪exchange▪bindKey▪queue▪Customer•Nginxo单个IP访问频率过多拉黑设置o过滤IP方式▪1.过滤单个IP▪2.过滤地址段▪3.过滤所有地址▪4.只允许单个IPo负载均衡▪轮询▪一致性Hash▪加权•MongoDBo什么是MongoDB▪MongoDB是一个文档数据库,提供好的性能,领先的非关系型数据库。o存储结构▪BSON•什么是BSONo一种类似JSON的二进制的存储格式•与JSON的区别o多了date类型与二进制的数据oNoSQL▪NotOnlySQLo优点▪存储结构易扩展▪查询速度更快oGridFS▪存储大量小文件功能•例如:存储用户头像o一条文档最大16Mo分片技术▪分片是将数据水平切分到不同的物理节点。当应用数据越来越大的时候,数据量也会越来越大。当数据量增长时,单台机器有可能无法存储数据或可接受的读取写入吞吐量。利用分片技术可以添加更多的机器来应对数据量增加以及读o支持的数据类型▪String,Integer,Double,Boolean,Object,ObjectID,Arrays,Min/Maxkeys,Datetime,keys,RegularExpression等ObjectIDIDIDID、三个字节的增量计数器•设计模式o支持主键外键关系▪默认是不支持的,需要硬编码,实现难度较大且不够直观o基本命令▪创建索引•db.collection.createIndex()▪查询•db.collectionName.find({key:value})▪更新•db.collection.update({key,value},{$set:{key:value}})▪删除•db.collection.remove()o场景▪1.随时应对动态增加的数据项时可以优先考虑使用NoSQL数据库▪2.在处理非结构化/半结构化的大数据时▪3.在水平方向上进行扩展时MongoDB▪MongoDB支持存储过程,它是javascript写的,保存在db.system.js表o事务o索引o一些查询指令▪大于小于•$gt$lt$gte$lte▪数组包含•{$elemMatch:{$eq:key}}{$elemMatch:{$eq:{name:1}}}o不支持事务▪更多的是在代码层面去对事务有所实现o1.单例模式▪懒汉▪饿汉▪双重检查•volatileo2.工厂模式o3.代理模式o4.策略模式o5.状态模式o6.观察者模式o7.模板模式o8.建造者模式o9.适配器模式o10.装饰器模式•JVMo内存泄漏▪定义•该被释放的对象没有释放,一直被某个或某些实例所持有却不再被使C▪解决•1.尽早释放无用对象的引用好的办法是使用临时变量的时候,让引用变量在推出活动域后自动设置为null,暗示垃圾收集器来收集该对存泄漏。•2.程序进行字符串处理时,尽量避免使用String,而应该使用ing•3.尽量少用静态变量因为静态变量是全局的,存在方法区,GC不会回收•4.避免集中创建对象,尤其是大对象,如果可以的话尽量使用流操作•5.尽量运用对象池技术以提高系统性能•6.不要在经常调用的方法中创建对象,尤其忌讳在循环中创建对象•7.优化配置▪达到一定质变即会引起内存溢出ojava程序运行较慢▪GC为了能够正确释放对象,GC必须监控每一个对象的运行状态,包括对象o垃圾回收▪垃圾回收器•CMS•G1▪回收机制•标记-清除算法•标记-整理算法•标记-复制算法▪分代回收•年轻代•老年代•永久代/元空间o内存模型▪堆▪栈▪方法区▪本地方法栈▪程序计数器ojava类的加载机制▪定义•1.代码被编译器编译后生成的二进制字节流(.class)文件•2.JVM把Class文件加载到内存,并进行验证、准备、解析、初始化•3.形成被JVM直接使用的Java类型▪流程•加载-》验证-》准备-》解析-》初始化-》使用-》卸载•面试点o类的初始化时机▪主动引用实例。即通过new的方式,new一•调用类的静态变量(非final修饰的常量)和静态方法•通过反射对类进行调用。•初始化某个类的子类,则父类也会被初始化•Java虚拟机启动时,指定的main方法所在的化。▪被动引用•子类调用父类的静态变量,只有父类初始化,•通过数据定义引用类,不会触发类的初始化•final常量不会触发类的初始化,因为编译阶段o类的生命周期▪开始当一个类被加载、连接、初始化后,它的生命周期▪当这个类的class对象不再被引用,即类不可触及时,Class对象就会结束生命周期。这个类在方法区的数据。▪总结•所以,一个类结束生命周期,取决于代表它的▪类的加载器•种类o启动类加载器:BootStrapClassLoader▪主要来加载java核心类库,无法被直接调用o扩展类加载器:ExtensionClassLoader▪用来加载jvm提供的扩展类库中的java类o系统类加载器:SystemClassLoader▪Java应用都由他来加载o用户自定义ClassLoader,继承抽象类ClassLoadero生命周期▪执行了System.exit()方法.▪程序正常执行结束。▪程序在执行过程中遇到了异常或错误而并未处理,导致异常终止。▪由于依赖的操作系统出现错误,而导致Java虚拟机进程终止。o性能调优▪1.设置堆的最大最小值•-xms-xmx▪2.调整年轻代老年代的比例▪原则就是减少gcstwoSTWdSTWJava用程序的其他所有线程都被挂起(除了垃圾收集帮助器之外)。Java中一种全与JVM交互;这些现象多半是由于gc引起。oFullGC内存泄漏排查▪jasvism▪dump▪监测配置自动dumpoCPU100%▪Top命令查看进程资源消耗,然后是jdkbin目录下的jstack命令查看堆栈信息找出对应出现问题的代码位置o内存溢出▪内存大小不够;是指程序在申请内存时,没有足够的内存空间供其使用,出现outofmemory;比如申请了一个integer,但给它存了long才能存下的数,•多线程o线程池▪参数意义•核心线程数corePoolSizeo默认无线程,接到任务就常见,除非初始预创建,一个或者全部•最大线程数maximumPoolSizeo当workQueue满后,线程总数小于maximunPoolSize时,创建线程处理任务•空闲时间keepAliveTimeo线程数大于corePoolSize时,无任务时线程终止•缓冲队列workQueueoLinkedBlockingQueue▪无界队列•无界:小心内存溢出oArrayBlockingQueue▪运行机制•流程o1.默认无线程数(不初始创建),任务来了就创建新的线程o2.如果任务过来,线程池中的线程数小于corePoolSize,也会新增线程去处理任务;o3.当任务过来,线程池中的线程数等于corePoolSize时,workQueue未满,会将任务新加入到queue中;o4.若任务过来,线程池中的线程数等于corePoolSize且workQueue中任务已满,但线程数小于maximumPoolSize,还会创建新的线程去处理任务;o5.若任务过来,线程总数等于maximumPoolSize,workQueue已满,则触发拒绝策略;•优先级ocorePoolSize>WorkQueue>MaximumPoolSize>拒绝策略▪拒绝策略•抛异常•丢弃•重试•丢弃最早提交的任务▪状态•new•runnable就绪o等待cpu的调度▪start()后•runningocpu调度后•blockingosleep()后,等待cpu的重新调度•deado执行完毕▪什么时候需要用到线程池•当线程创建与销毁的时间大于线程任务执行的时间o多线程一定是最快的吗▪不一定•redis是单线程的o因为IO操作时,常发生阻塞,这时多线程的强大就体现出来了▪多线程会频繁切换线程上下文o方法▪join()•等待该线程先执行完毕后才会往下执行▪wait()•释放锁•不阻塞▪yiely()•让出cpu的使用权,重新让所有线程争抢cpu执行机会▪sleep()•阻塞•不释放锁onotify()与notifyAll()有什么区别•IOoBIOoNIOo粘包拆包o多路复用oNettyo序列化•MQTT协议o介绍▪轻量级基于代理的发布/订阅的消息传输协议▪TCP/IPo协议▪QOS服务质量•Qos=0o客户端只发一次,无论是否收到,▪导致只会消费一次消息•用于一些不是很重要的数据•Qos=1o客户端发送一次消息,服务器给个回复,客户端若没收到,一直发送▪导致会产生至少一个消息•比如状态的变更,多收一次也没关系•Qos=2o客户端缓存消息,并发送给服务端,服务端收到并缓存消息,并给回复消息,客户端收到后在发个消息给服务端,服务端收到后发送消息给订阅端,并发消息给客户端,客户端把缓存的消息删除,订阅方收到消息后,缓存消息,给服务端发个收到消息,服务端又发个回复消息,订阅方消费信息,删除消息,并发给服务端一个完成的消息,服务端删除消息,▪确保一次传输o发布方与服务器有四次通信,一次消息发送,两次消息的互相确认,一次服务器发给发布方完成的消息o订阅方不一定要在线o第三方:EMQ服务器▪共享订阅•集合oHashMap▪1.7•数组+链表oEntry•头插•会产生什么问题o1.resize()扩容的时候,rehash重新插入时产生环形链表,调用get方法后发生死循环•扩容o条件▪条件1:总size大于阈值(数组长度*加载因子)的时候▪条件2:存放新值的时候与当前存放的数据发生Hash碰撞▪1.8•数组+链表+红黑树o当链表长度大于8的时候,且数组长度大于64的时候,转化。oNode▪hash,key,value,next•尾插o解决环形链表,防止死循环•扩容o存放新值时,数组数据总数大于阈值,并不要求发生hash碰撞▪扩容机制•新数组为原数据大小的两倍,数据重新hash,重新放入数组中▪多线程不安全•1.7o形成环形链表,发生死循环,丢失数据•1.8o多个线程插入同一位置,导致数据丢失▪疑问•为何1.8加入红黑树o默认使用二分法查询红黑树,查询效率更高•为何1.8改为尾插法o不会产生环形链表,解决死循环问题•为何扩容需要重新hasho获取index值与数组长度有关▪扩容为2的次幂•方便位运算•数据均匀分布▪遍历•1.entrySet()然后获取迭代器遍历•2.建一个BiCusumer的子类,用forEach()遍历•3.用keySet()然后获取key的迭代器遍历•4.用values()进行值遍历oHashTable▪线程安全,性能不佳原因•所有方法都加了synchronized,使线程串行oConcurrentHashMap▪1.8前•锁分段技术(Segment)继承了ReentrantLocko数据分为16份,分别加锁•扩容:将每段Segment下的数组扩大至两倍o优点:快速定位和减少重排次数▪1.8后•放弃了索锁分段技术•CAS+Synchronized▪CAS•比较和替换▪不接受NullKey与NullValue▪数组+链表+红黑树▪安全失败•采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历。▪为何是线程安全的•Segment分段锁,将数据分为16份,分别加锁•CAS+Synchronized▪类加载器•BootstrapClassLoadero所以可以使用Unsafe.getUnsafe()方法oArrayList▪数组▪查询快(按角标查询),删除新增较慢▪线程不安全oLinkedList▪带有头结点与尾节点的双向链表▪插入方式有两种,头插与尾插▪查询比较慢,删除新增比较快o快速失败▪java.util下的集合类ArrayList,HashMap等•在使用迭代器对集合对象进行遍历的时候,如果A线程正在对集合进行遍历,此时B线程对集合进行修改(增加、删除、修改),或者A线程在遍历过程中对集合进行修改,都会导致A线程抛出ConcurrentModificationException异常。•动态代理ocglib动态代理oJdk动态代理•Mybatiso#与¥的区别▪#{}使用的预处理模式▪${}使用的字符串替换的方式oDao与xml方法匹配▪mapper标签上的namespace指定o嵌套查询与嵌套结果o插入数据获取ID▪1.设置useGeneratedKeys▪2.selectKey•selectLAST_INSERT_ID();oSqlSession后续执行▪1.SqlSession中有executor▪2.executor默认指向CachingExecutor,对象中有二级缓存,不走缓存就走delegate(装饰器)BaseExecutor的query▪3.BaseExecutor抽象类的query中存在一级缓存,若不走缓存,实际走的就是三个执行器的doQuery函数o执行器▪SimpleExecutor•不重复使用预处理•select或者update▪ReuseExecutor•select或者update•重复使用预处理o不关闭statement对象,放入map中重复使用▪BatchExecutor•必须手动的刷新oexecutor.doFlushStatements(),简称批处理刷新o缓存▪一级缓存•概要•缓存的命中条件o1.同一会话o2.方法名,类名必须一致(statementid必须一致)o3.RowBounds结果条数一致,结果范围一致o4.sql一致,参数一致•如何保证数据一致性•会话级缓存o必须是同一会话才会命中•缓存Map的key值是什么oCacheKey▪BaseExecutor的createCacheKey方法•参数:statementID,offset,limit,sql,参数o决定命中条件▪如何判断两个CacheKey相等•两个cachekey对象的HashCode是否相等•判断checksum是否相等oupdate时checkSum+=HashCode•判断count是否相等oupdate时count++•逐一判断以上五个元素是否相等▪二级缓存•应用级别的缓存o随应用的生命周期•缓存Map的key值是什么•默认是不开启的o需要在xml中配置cache标签▪eviction缓存回收策略•1.软引用•2.弱引用•3.先进先出o按照缓存进入的顺序来移除它们•4.最少使用的o移除最长时间不被使用的对象o可以全局配置▪cacheEnabled•共享缓存中数据进行序列化操作和反序列化操作o实现Serializable▪共同•修改操作o清除缓存操作▪因为不需要访问缓存并会更改数据•缓存采用同一个缓存基类,二级缓存实现比较复杂,一级比较简单;所以二级缓存比一级缓存复杂的多o动态SQL▪where,if,foreach,set,wheno表中字段与对象属性名不一致▪1.sql语句中使用as转换▪2.xml中使用resultMap的property,column属性建立映射关系▪3.如果是驼峰命名与下划线形式,可以使用全局配置mapUnderscoreToCamelCase=true来配置o批量插入如何实现•Session与CookieoCookie▪浏览器禁用后Session不可使用,可使用URL重写:URL拿到就可以登录▪客户端▪最大为4K▪大部分浏览器最大可以设置20个Cookieo都是会话跟踪技术oSession▪服务端▪session的实现依赖于Cookie,SessionId存在Cookie中•Jenkins•K8S•SpringBoot•ZooKeepero选举机制•Git•秒杀系统o限流(拦截请求)o客户的恶意下单•锁osynchronized▪底层实现原理•方法oACC_SYNCHRONIZED▪执行线程需要先获取到monitor•代码块omonitorenteromonitorexito程序计数器▪enter加1,exit或者异常减一•两者区别o方法:设置ACC_SYNCHRONIZED实现▪jvm层面▪锁膨胀(锁升级)•过程o无锁o偏向锁▪利用了对象头中的ThreadId不会释放▪比较对象头中的ThreadID是否与自身一致,一致则变为无锁状态,不一致则判断对方是否存活,存活则升级为轻量级锁,死亡则变为无锁状态▪JVM参数•偏向锁是默认开启的,而且开始时间一般是比应用程序启动慢几秒,如果不想有这个延迟,那么可以使用-XX:BiasedLockingStartUpDelay=0;ovolatile•不想要偏向锁,那么可以通过-XX:-UseBiasedLocking=false来设置;o轻量级锁▪自旋获取资源o重量级锁•原因o发生了资源的争抢•缺点o升级不可逆▪特征保证•可见性o内存强制刷新•可重入性o计数器•原子性o单一线程持有•有序性oLock▪底层实现原理▪jdk层面▪ReentrantReadWriteLock•ReadLock•WriteLock▪ReentrantLock•FairSync•NonfairSyncoCAS▪2▪如何保证不同线程可见性•被volatile修饰的变量,在发生写操作时,会发出一个汇编指令,这个指令会触发mesi协议,会存在有一个总线嗅探的东西,这个总线嗅探会让cpu不断检测主内存中该变量的值,一旦有变化,其他的cpu会立即将该变量从自己的缓存中清除,再去主内存中去重新获取这个值▪缓存行锁定•在store之前lock,write回主内存之后unlock,解决了并发写问题▪一个线程改变值后,另一个线程立刻知晓▪作用•1.保证内存可见性o保证修改了volatile的值会立即更新到主存,其他的线程操作时都会获取新值•2.防止指令重排▪volatile仅能实现变量的修改可见性,不能保证原子性•比如说,对基本数据的操作,都分为三步,从自己线程缓存中拿出,操作,再写入缓存,再写入主存•然后,如果说取出数据后,cpu切出,另一个线程对该值操作,并成功写入主存,切回来后,操作完重新写入。o锁的分类▪1•乐观锁o拿不到锁继续执行▪CAS•悲观锁o拿不到锁一直尝试去拿锁▪常见的线程锁▪乐观锁策略•公平锁•非公平锁▪3•重入锁•不可重入锁▪死锁•条件o1.互斥▪都需要等待其他线程释放锁o2.不可抢占o3.占有且等待o4.循环等待▪形成等待环路o2.不可抢占•简介o线程A拿着锁等待B释放,线程B拿着锁等待B释放•破坏o不会破坏1o破坏2,线程A等待另一个资源,一段时间主动释放持有资源o3,每个线程一次性获取所有资源o破坏2,线程A等待另一个资源,一段时间主动释放持有资源o3,每个线程一次性获取所有资源oCAS(无锁)▪CAS的作用是比较当前工作内存中的值和主内存中的值,如果相同则执行规定操作,否则继续比较直到主内存和工作内存中的值一致为止▪存在的问题•ABA问题o解释▪因为CAS会检查旧值有没有变化,这里存在这样一个AB,然后再ACAS发现旧值并没有变化依o解决▪可以沿袭数据库中常用的乐观锁方式,添加一个版本号•自旋时间过长o使用CAS时非阻塞同步,也就是说不会将线程挂起,会自旋 (无非就是一个死循环)进行下一次尝试,如果这里自旋时间过长对性能是很大的消耗。•只能保证一个共享变量的原子操作o解释o解决方案▪利用对象整合多个共享变量,即一个类中的成员变量就是这几个共享变量。然后将这个对象做CAS操作就可来保证引用对象之间的原子性。oCASvsSynchronized▪主要的区别•CAS并不是武断的间线程挂起,当CAS操作失败后会进行一定的尝时的挂起唤醒的操作,因此也叫做非阻塞同步。o当对一个共享变量执行操作时CAS能保证其原子性,如果对多个共享变量进行操作,CAS就不能保证其原子性。•元老级的Synchronized(未优化前)最主要的问题是:在存在线程竞争的情况下会出现线程阻塞和唤醒锁带来的性能问题,因为这是一种互斥同步(阻塞同步)。o操作系统的临界区机制▪牵扯到用户态与内核态之间的转变oSynchronized与Lock区别▪1.Synchronized是jvm的底层实现,而Lock是jdk的一个接口,提供了各I▪2.Synchronzied会自动释放锁,Lock需要手动unlock▪3.Synchronized会自动中断,而Lock可以中断也可以不中断▪4.Synchronized可以锁方法与代码块,lock只能锁代码块▪5.Synchronized是非公平锁,ReentrantLock可以指定是否为公平锁▪6.Synchronized不能知道线程有没有拿到锁,而Lock能▪7.Lock可以使用读锁提高线程读效率▪劣势:锁的升级不可逆oThreadLocal▪ThreadLocal是一个本地线程副本变量工具类▪线程隔离特性▪什么时候用•将私有线程和该线程存放的副本对象做一个映射,各个线程之间的变特别适用于各个线程依赖不同的变量值完成操作的场景。▪ThreadLocalMap•ThreadLocalMap是ThreadLocal的内部类,没有实现Map接口,•Entryokey只能是ThreadLocal对象•Hash冲突怎么解决o和HashMap的最大的不同在于,ThreadLocalMap结构非常简单,没有next引用,也就是说ThreadLocalMap中解决Hash冲突的方式并非链表的方式,而是采用线性探测的方式•线性探测o初始key的hashcode值确定元素在table数组中的位置,如果发现这个位置上已经有其他key值的元素被占用,则利用固定的算法寻找一定步长的下个位置,依次判断,直至找到能够•内存泄漏▪ThreadLocal在没有外部对象强引用时,发生GC时弱引用Key会被回收,而Value不会回收,如果创建ThreadLocal的线程一直持续运行,那么这个Entry对象中的value就有可能一直得不到回收,发生内存泄o解决remove方法,将Entry节点和Map的引用关系移除,这样整个Entry对象在GCRoots分析后就变成不•Linuxo1.查询进程ps-ef|grepxxxo2.动态查看日志tail-fxxx.logo3.查看所有用户▪cat/etc/passwd•条目:admin:x:1000:1000:centos-loumt:/home/admin:/bin/bash•解释:用户名:用户密码(文件不安全,移至/etc/shadow中):用户ID:组ID(与/etc/group有关):注释:家目录:可以看成是否可以登录,/sbin/nologin就是不可以登录o4.tar包▪taro5.从某个文件内查询某个内容▪grep"内容"文件路径•分布式o分布式锁▪1.Redis的RedLock▪zk锁o分布式事务一致性•Java基础o三大特性▪封装•面向对象的封装即是将一个对象的属性与行为定义在一个类中,其中私有不公开的用private去修饰,公开的用public修饰,也提供修改属性的set与获取属性的get▪继承•可以使用一个基础类来定义一个更具体的类,用关键字extends该基础类,可以修改基础方法,新增属性与行为,提供代码的重用性,也体现了该语言的扩展性▪多态•编译时与运行时类型不一致就是多态性,多态增强了软件的灵活性和o同步异步▪相对于服务器而言•数据结构•触发IO时,同步等待其返回,数据返回后才继续往下,异步是不等待返回值直接往下走,内核通知后结果返回o阻塞非阻塞▪相对于客户端而言•简单理解为需要做一件事能不能立即得到返回应答,如果不能立即获得返回,需要等待,那就阻塞了,否则就可以理解为非阻塞。oservletofiltero内存模型(JMM)oJDK与JRE的区别▪JRE是Java基础运行环境,包含JVM与Java核心类库▪JDK是Java开发环境,包含除JRE以外的Java开发工具,如Javac.exe,Jar.exe,Java.exeoJVM是Java虚拟机,是Java能够跨平台的核心o序列化与反序列化有什么作用▪转储•两种介质之间的传输,比如内存到数据库,比如对象在网络上的传输▪序列化:对象转为有序字节流▪反序列化:字节流转为对象•Java工具oJMeter▪多线程测试工具oPostManoJava反编译▪javap-v*.class•缓存与数据库在高并发中不一致解决方案如下:更新数据的时候,根据数据的唯一标识,将操作路由之后,发送到一个jvm内部队列中。读取数据的时候,如果发现数据不在缓存中,那么将重新读取数据+更新缓存的操作,根据唯一标识路由之后,也发送同一个jvm内部队列中。一个队列对应一个工作线程,每个工作线程串行拿到对应的操作,然后一条一条的执行。这样

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论