
面试
文章平均质量分 95
面试整理
-代号9527
逢山开路,遇水搭桥!纸上得来终觉浅,绝知此事要躬行。
展开
-
【Java面试】二十三、项目相关
前面提到,在交易平台要做一些校验和消费记录落库的操作,这些是对接所有三方系统的公共步骤,而后面请求第三方系统接口肯定要做的鉴权认证以及转发或者调用,则属于各个三方系统的定制化行为。因为不同的第三方供应商系统有不同的认证方式,想实现打通,就要有不同的具体策略类(比如策略类A是通过appid完成认证,策略类B是通过密钥完成认证),因此考虑使用了策略模式。用户在浏览器发送请求数据到后台系统,期间数据在网络传输,如果这些数据是敏感数据,被恶意拦截时,就有安全问题,造成用户密码泄漏等等。原创 2024-06-25 11:12:34 · 673 阅读 · 0 评论 -
【Java面试】二十二、JVM篇(下):JVM参数调优与排查
再比如栈大小的设置,一般256KB,用于存放每个线程的栈帧,这个值太大,则从栈可用空间层面限制了最大线程数量,比如设置了512KB,在总内存不变的情况下,线程数量上限就减半。内存泄漏,即一些对象没有被回收,累积导致OOM,表现为运行一段时间后服务宕机,但生产环境不能等服务挂了再修,可选择监控+告警邮件,比如普罗米修斯,让内存占用到一定阈值后,触发告警,此时可选择VisualVM分析。通过查看堆信息的情况,可以大概定位内存溢出是哪行代码出了问题,找到对应的代码,通过阅读上下文的情况,进行修复即可。原创 2024-06-19 19:30:44 · 944 阅读 · 0 评论 -
【Java面试】二十一、JVM篇(中):垃圾回收相关
JVM处理class字节码文件成为二进制文件,类加载的作用则是将class字节码文件加载到JVM中。启动类加载器:加载JDK下的jre/lib下的类,这个加载器由C++实现扩展类加载器:加载JDK下的jre/lib/ext下的类,如果把开发者自己写的class放这个目录,也会被扩展类加载器加载应用类加载器:加载开发者自己写的class自定义类加载器:自己去继承ClassLoader,自己实现。原创 2024-06-19 16:38:02 · 961 阅读 · 0 评论 -
【Java面试】二十、JVM篇(上):JVM结构
根据JVM策略,新创建的对象在伊甸园区,伊甸园区满了以后,触发Young GC,GC后或者的对象,复制到幸存者区,后面每GC一次,活着的对象年龄加一(对象头里存着年龄),对象GC年龄到达阈值(如15)后,晋升到老年代。因为永久代/方法区或者说后来的元空间,存储的主要是一些类信息和常量,需求开发,加载的类越来越多,这个空间不可控,移除永久代,在本地内存放个元空间,可以防止OOM。栈,即每个线程运行时需要的内存空间,保存着该线程方法调用的基本数据,先进后出,其中,每一个调用的方法用一个叫栈帧的东西存。原创 2024-06-18 20:45:19 · 924 阅读 · 0 评论 -
【Java面试】十九、并发篇(下):线程池
以银行为例对比:银行大厅一共有10个窗口(最大线程数量),但平时一般只开5个(常驻线程数量),某天办理业务的人很多,5个窗口不够用,其余人来了就先在大厅椅子上坐着等(阻塞队列),结果椅子坐满了,还有人陆续来,于是10个窗口全开,还来很多人,那就只能告诉新来的今天轮不到你办了(拒绝策略)。最后,如果是并发高且每个业务执行时间也长,那这是优化重点就不是线程池了,而是整体架构,比如是否加入缓存,是否增加服务器,再看核心数是N+1 还是 2N+1。若线程池长度超过了处理需要,则灵活回收空闲线程,反之,则新建线程。原创 2024-06-12 20:56:46 · 1093 阅读 · 0 评论 -
【Java面试】十八、并发篇(中)
AQS,抽象队列同步器,包含三个核心抽象类,是多线程中的队列同步器,是一种锁机制,是JUC的基石,它做为一个基础框架使用,像ReentrantLock、信号量Semaphore、计时器CountDownLatch 都是基于AQS实现的AQS内部维护了一个先进先出的双向队列,队列中存储的排队的线程(把排队的线程封装成一个个Node对象存FIFO队列,像银行办业务,没轮到办理的人去椅子上排排坐)原创 2024-06-11 19:59:20 · 866 阅读 · 0 评论 -
【Java面试】十七、并发篇(上)
线程Thread1执行到synchronized代码块,如果对象的Monitor对象的Owner属性为null,则抢锁成功,后面其他线程再进来抢锁,就进入EntryList阻塞,直到Thread1执行完释放锁,EntryList里的线程又开始争抢锁(并非先来后到的排队),WaitSet即存调用了wait方法的线程。t1线程从主内存读到i=5,+1后准备把6写回主内存,此时,比较期望值5和内存中的实际i值,若相等,则乐观的认为自己运算的期间没有其他线程修改i,就将i写回主内存。原创 2024-06-09 20:05:12 · 935 阅读 · 0 评论 -
【Java面试】十六、并发篇:线程基础
如上,主线程中调用t2.interrupt(),t2线程的中止标志位变为true,但是否中止执行,看 t2 线程自己,上面t2线程自己判断标志位为true时,就break结束循环。Runnable:可执行状态,执行start方法,此时如果抢到了CPU时间片,那就去执行run方法,然后线程进入终止状态(死亡)Waiting:调用了wait方法,进入等待状态,其他线程调用notify方法后被唤醒,进入Runnable状态。加一个标记字段,改了标记之后,线程return,结束执行。以下,t2线程中执行。原创 2024-06-09 16:56:14 · 1010 阅读 · 0 评论 -
【Java面试】十五、HashMap相关
关于上面拆分链表的举例,往新数组搬时,比如下标3的位置,是一个链表,那扩容时,遍历链表上的每一个Node e,计算(e.hash & oldCap),若为0,则扩容前后,该Node所在的位置不变,之前挂下标为3的链表里,那扩容后还挂下标为3的链表里。PS:JDK1.7下,HashMap扩容时,因为是头插法(比如下标1的位置上,Node链为Node A -> NodeB ,迁到新数组就是Node B -> NodeA),并发时,就可能会出现死循环,因此,JDK1.8时改为了尾插法。这也是红黑树自平衡的原因。原创 2024-06-05 18:12:33 · 1036 阅读 · 0 评论 -
【Java面试】十四、LinkedList相关
代码实现如下,假设链表中有个B结点,其下一个结点为C,则B.next == C。因此,可以支持双向遍历。原创 2024-06-04 21:09:52 · 1158 阅读 · 0 评论 -
【Java面试】十三、ArrayList相关
ArrayList、LinkedList、HashMap等集合,从其前缀可知其对应的数据结构为数组、链表、哈希表。从数据结构,也可反推出集合的结构。原创 2024-06-04 20:38:53 · 1065 阅读 · 0 评论 -
【Java面试】十二、Kafka相关
topic分区的消息,只能由消费者组的唯一一个消费者处理,因此,不同的分区分给了不同的消费者,如图,consume1负责P1、P2,consume2负责P3,consume3负责P4分区。分区内部,存储了数据,且是分段存储,segment,每一段,对应三个文件,.index索引文件、.log真正的数据文件、.timeindex时间索引文件。以上两种写法都可,第一种写法指定分区,第二种写法用key,key被hash后,分到不同的区,因此,同一个业务,用相同的key即可。这么写代码,重复消费的问题还在,因此,原创 2024-06-04 15:27:46 · 1679 阅读 · 0 评论 -
【Java面试】十一、RabbitMQ相关
队列ttl.queue绑定了死信交换机dl.direct,dl.direct又关联了队列,最终死信会被绑定了死信队列的消费者处理 ⇒ 死信交换机 + TTL = 延迟队列。此时,如果这个队列配置了dead-letter-exchange属性,指定了一个交换机,则死信被投递到这个交换机(即死信交换机,Dead Letter Exchange,DLX)此外,选择auto时,还可以利用Spring的retry机制,在消费发生异常时,重试一定次数,仍然失败则扔到一个异常交换机里,后续人工处理。原创 2024-06-04 11:09:18 · 838 阅读 · 0 评论 -
【Java面试】十、微服务篇-分布式(下)
提交事务后,各个分支事务向TC报告自己的事务状态到TC,即告诉TC,自己的SQL执行成功没有,都成功,则删除undo-log日志,有一个失败,则根据undo-log把其余分支事务的数据退回去。分支事务各自执行业务SQL后,不提交分支事务,等待TC检查各个分支事务,如果各个分支事务的SQL执行都没报错,则通知分支事务一起提交事务,反之,通知各个分支事务一起回滚事务。最后,加节点,是多了个干活儿的人,提到的是并发上限,单个接口,响应该几秒还是几秒,因为处理某个接口的这个活儿,你交给哪个人去干,都是那个耗时。原创 2024-06-03 17:37:22 · 1388 阅读 · 0 评论 -
【Java面试】九、微服务篇-SpringCloud(上)
方式一:在服务消费方(发起调用的那一方),创建IRule的Bean,返回一个IRule接口的实现类,不同的实现类,对应上面的一个个策略。如此,order调用任何一个微服务,都是这种负载均衡策略。方式二:在配置文件中,针对调用哪一个微服务时,使用哪种策略,局部生效,只针对order调用user这一个微服务时生效。原创 2024-06-03 13:52:57 · 1415 阅读 · 0 评论 -
【Java面试】八、MyBatis篇
执行user.getOrderList时,才会执行查订单的SQL,注释调user.getOrderList,查订单的SQL直接不会去执行。MyBatis延迟加载,即查询用户时,暂时不要去查询订单数据。当调用了user.getOrderList时,再去执行查订单的SQL。反之,一次都查出来,是立即加载。MyBatis的一级、二级缓存,都是基于PerpetualCache,本质是一个HashMap。用户表和订单表一对多的关系,一个用户有多个订单。原创 2024-06-03 10:09:06 · 832 阅读 · 0 评论 -
【Java面试】七、SpringMvc的执行流程、SpringBoot自动装配原理
旧项目中,未前后端分离时,用到JSP,相关流程为:请求达到前端控制器DispatcherServlet,它相当于一个调度中心,会加载处理器映射器、处理器适配器、视图解析器。DispatcherServlet被Tomcat容器初始化,所有的请求先经过它。DispatcherServlet向处理器映射器去查询handler,即查询这个接口该调哪个Controller的哪个方法。处理器映射器里以key-value形式存了接口路径合类名+方法名流程总结:不再返回一个ModelAndView,而是返回一个J原创 2024-05-31 14:54:01 · 1369 阅读 · 0 评论 -
【Java面试】六、Spring框架相关
接下来B需要依赖注入A这个Bean时,会去从二级缓存中获取,然后B这个Bean创建成功,存储到一级缓存的单例池中,同时,将B在二级缓存中的半成品删掉。AOP,面向切面编程,将那些公共的逻辑代码,抽取封装,匹配要切入的点,实现统一加功能的操作。由Bean的生命周期可知,刚开始,从Beanfinition获取构造方法,反射拿到半成品的A这个Bean,即纯净态的Bean,此时,没有依赖注入,即b属性为null。同A,纯净态的B,在实例化时,依赖注入,设置a的属性,发现需要A这个Bean。原创 2024-05-31 13:51:49 · 757 阅读 · 0 评论 -
【Java面试】五、MySQL篇(下)
改为可重复读的隔离级别后,又出现了幻读 ⇒ 幻读即:事务A先查id=1数据,发现没有。隔离级别改为读已提交后,发现会出现两次读取的结果不一致的情况 ⇒ 不可重复读即:A刚开始读的id=1的数据,值为x,期间事务B又更新并commit了id=1的这条数据,此时A事务第二次读,发现两次数据不一样。当然,事务的隔离性还有锁在处理,比如一个事务获取了一行数据的排他锁,那其他事务就不能再获取该行的其他锁,其他事务如果尝试获取这行数据的共享锁或排他锁,都会被阻塞,直到持有排他锁的事务释放锁或事务结束。原创 2024-05-27 21:16:53 · 1145 阅读 · 1 评论 -
【Java面试】四、MySQL篇(上)
如果去维护一个类似二叉树的结构,再查age=45的数据,则直接从根节点开始⇒ 45 > 36,去右侧 ⇒ 45 < 48 ⇒去左侧 ⇒ 查找完毕,如此,查找效率提升,这即索引的思想。是覆盖索引,虽然select * ,但其where是根据id过滤的,即用的是主键索引、聚簇索引,索引的叶子节点存了整行数据,需要返回的字段,在索引中能够全部找到。给name字段加了非聚簇索引,因此,执行如上SQL,先根据name的非聚簇索引的B+树 ⇒ A小于L,走左边,到G和J,再走左边,找到Arm ⇒ 因为是。原创 2024-05-27 15:50:29 · 1178 阅读 · 0 评论 -
【Java面试】三、Redis篇(下)
若此时master宕机,没来得及同步到slave,然后主从故障转移,从slave中选出一个新的master,线程2又来获取锁,此时,对新的master,自然可以set成功,即获取分布式锁成功,如此,就出现了两个线程同时获取到了分布式锁。线程1查完库存,num=1,挂起,同时线程2执行,查库存,num=1,此时,线程2被挂起,线程1抢完券,改库存减一,库存为0。此外,线程A持有分布式锁的时候,线程B再来尝试获取锁,如果获取失败,会while循环尝试加锁,循环次数达到阈值后,还没获取成功,则返回获取锁失败。原创 2024-05-22 18:31:17 · 1248 阅读 · 0 评论 -
【Java面试】二、Redis篇(中)
根据前面的写时复制机制,basave期间,master接收到的写请求不会同步到快照文件中,因此,slave加载完快照文件后,还要执行从master收到的repl_baklog文件,该文件记录了basave期间,master额外收到的写指令。机制,此时,原内存空间为read-only,主进程如果要进行写操作,会拷贝一份数据,进行写操作,且后面读操作也是基于拷贝的副本去读,因此,basave期间,进行更新的那部分数据,不会同步到快照文件中。如果Redis实例宕机,也可读取快照文件,恢复数据,一般。原创 2024-05-22 16:07:08 · 837 阅读 · 0 评论 -
【Java面试】一、Redis篇(上)
请求2进来(对应线程2),其进行了update,改库,并删缓存,此时,库中为20,缓存中为null。然后新的请求进来(对应线程2),CPU切到线程2执行,查缓存未命中,线程2去查库 + 写入缓存,线程2执行结束,此时缓存为10,库中为10。缓存未命中,查库前,获取一个互斥锁,获取不到则一直重试,如此,后面的线程走不到查库这一步,直到线程1完成查库+写入Redis,其余线程就会命中缓存。理想状态为:线程1删缓存,再更新数据库,后面请求过来(对应线程2),先查缓存,未命中,去查库 + 写入缓存,一切正常。原创 2024-05-21 18:44:18 · 965 阅读 · 0 评论 -
【Spring面试】十、SpringBoot相关
SpringBoot的用来快速开发Spring应用的一个脚手架、其设计目的是用来简化新spring应用的初始搭建以及开发过程。二者不是一个层面的东西,没有可比性。@SpringBootApplication:常用于启动类,标记这个应用是一个SpringBoot应用@SpringBootConfiguration:这个注解其实就是@Configuration,表示启动类是一个配置类@EnableAutoConfiguration:向Spring容器中导入一个Selector,用来加载类路径下的SpringF原创 2023-09-13 13:41:46 · 594 阅读 · 0 评论 -
【Spring面试】九、Spring MVC相关
如果所有的Bean都交给父容器,SpringMVC在初始化HandlerMethods的时候(initHandlerMethods) ,无法根据Controller的handler方法注册HandlerMethod,并没有去查找父容器的bean,也就无法根据请求URI 获取到 HandlerMethod来进行匹配。可以,因为父容器的体现无非是为了获取子容器不包含的bean,如果全部包含在子容器完全用不到父容器了,所以是可以全部放在springmvc子容器来管理的。异步事件发布是多线程。原创 2023-09-13 10:13:45 · 359 阅读 · 0 评论 -
【Spring面试】八、事务相关
Spring不支持,因为Spring事务信息存于ThreadLocal中的Connection,一个线程永远只能有一个事务,所以无法实现两个事务的一致性。Spring事务是把上面业务逻辑前后的事务开启与提交用AOP包了一下,即原理是:Spring事务底层是基于数据库事务和AOP机制。事务2只是改了余额,但并未提交,事务1就把这个没提交的值读走了,如果以后事务2最终回滚,就出问题了。事务1先读后去处理其他事儿,然后期间事务2修改并commit,等事务1再读,则产生数据不一致的问题。,与他们同成功,同失败。原创 2023-09-12 15:14:16 · 531 阅读 · 0 评论 -
【Spring面试】七、AOP相关
AOP(Aspect Oriented Programming),即面向切面编程,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑(如日志采集),抽取并封装形成切面(Aspect)后对已有方法或对象做一个增强,减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理等。AOP 与 OOP?AOP、OOP在字面上虽然非常类似,但却是面向不同领域的两种设计思想,OOP面向对象编程,针对的是业务处理过程的实体及其属性和行为进行抽象封装。原创 2023-09-12 09:57:26 · 278 阅读 · 0 评论 -
【Spring面试】六、@Autowired、@Configuration、第三方Bean的配置
第一种写法报错的原因是加载的顺序问题,@Autowired写在变量上的注入,要等到变量所在类完全加载完才注入,因此变量appConfig的加载要早于Info这个Bean,给appConfig赋值时,还没有注入。因为Spring在解析@ComponentScan的时候,拿到basePackage,如果没有设置,则将你的类所在的包路径做为扫描包的路径。@Autowired是通过Bean的后置处理器进行解析的,在创建一个Spring上下文的时候在构造函数中进行注册。是Spring依赖注入(DI)的方式之一。原创 2023-09-11 16:30:19 · 977 阅读 · 1 评论 -
【Spring面试】五、Bean扩展、JavaConfig、@Import
以上是应用层的区别,最后,从源码和流程上来说:大方向都是创建Spring容器(同一个接口,不同的实现类),然后加载、解析配置,再注册为BeanDefinition后交给Bean工厂生产。之所以分为三种,是因为开发一个项目,常使用三层架构,即控制层、业务层、数据返回层,提供这三个注解用于不同层,提高代码的阅读性。所以Bean的生产顺序是由BeanDefinition的注册顺序决定的,当然依赖关系也会影响Bean的创建顺序。refresh方法:(IoC容器的加载,就是在refresh方法里实现的)原创 2023-09-11 11:31:17 · 397 阅读 · 0 评论 -
【Spring面试】四、Bean的生命周期、循环依赖、BeanDefinition
如上图,实例化完BeanA,要属性注入了,此时发现需要依赖Bean B,在IoC容器中找Bean B,没找到,开始创建Bean B,实例化完做DI发现需要Bean A,结果在IoC中没找到Bean A,于是就开始重复上面的这个流程,形成死循环。线程1以微小优势先来创建bean,实例化后放进三级缓存,此时,没有属性赋值和初始化,线程2进来getBean,getSinfleton去三个缓存中找,就拿到了不完整的Bean。不完整的Bean,即只是完成了实例化,没有完成属性赋值(DI)和初始化(生命周期回调)。原创 2023-09-10 20:46:25 · 445 阅读 · 0 评论 -
【Spring面试】三、Bean的配置、线程安全、自动装配
Bean也是一个对象,但它是由Spring IoC容器管理的对象Bean是一个由Spring IoC容器实例化、组装和管理的对象一个个Bean创建出来,没有自动装配(纯净态Bean)时,如果它的一个属性是另一个对象,则没有自动装配时,这个属性自然为空。之前的这种方式是手动装配PS:对应的Java代码://...//...PS:对应的Java代码://...//...PS:对应的Java代码://...//...PS:对应的Java代码://...//...原创 2023-09-10 14:45:54 · 510 阅读 · 0 评论 -
【Spring面试】二、BeanFactory与IoC容器的加载
bean工厂的bean属性处理容器,说通俗一些就是可以管理我们的bean工厂内所有的beandefinition(未实例化)数据,可以随心所欲的修改属性。扩展点,即Spring Ioc在加载的过程中,其底层会对外提供很多的扩展接口或者一些钩子方法,当我们自己去实现这些接口时,Spring就会在特定的点,帮我们调用钩子方法,从而实现对Spring底层的扩展。,getObject方法返回的这个Bean,可以是被寄生的Bean的子类,也可以是和被寄生的Bean的这个类毫无关系的类。原创 2023-09-08 20:53:57 · 734 阅读 · 0 评论 -
【Spring面试】一、SpringBoot启动优化与Spring IoC
按照上面调试代码里的配置,则:正式厨师10个,可招兼职的最多20个,店里能做30人,门口10个小板凳。某一会,来了100个客人,则只能先安排40个,另外60个不会光速走人,会先观望一下,即有自己的超时时间,等到了超时时间,还没轮到他进去吃,则走人,msg为。要做一个体验良好的Starter,这个文件还是非常重要的,对于使用你封装的开发者来说,写配置的时候就会方便很多。通过Spring提供的IoC容器,集中管理对象,使得对象和对象之间的耦合度降低,避免硬编码造成的程序过度耦合,方便维护对象。原创 2023-09-06 21:24:05 · 853 阅读 · 0 评论