恒生电子面经(一面)
一面 1.11 20min
1、自我介绍
2、介绍简历项目
3、SpringBoot框架相关问题
Q:有没有用过自定义注解?
A:没有……(说了一些常用注解,如@TableId,@RequestMapping,@param,@return,@Override等)
【查阅补充】
注解本质是一个继承了Annotation 的特殊接口,其具体实现类是Java 运行时生成的动态代理类。而我们通过反射获取注解时,返回的是Java 运行时生成的动态代理对象。
java.lang.annotation 提供了四种元注解(元注解,专门注解其他的注解):
- @Documented:指定被标注的注解会包含在javadoc中。
- @Retention: 指定注解的生命周期(源码、class文件、运行时),其参考值见类的定义:java.lang.annotation.RetentionPolicy
- @Target:指定注解使用的目标范围(类、方法、字段等),其参考值见类的定义:java.lang.annotation.ElementType
- @Inherited:指定子类可以继承父类的注解,只能是类上的注解,方法和字段的注解不能继承。即如果父类上的注解是@Inherited修饰的就能被子类继承。
(JDK1.8新增了两种注解)
自定义注解自定义注解类编写的一些规则:
- Annotation 类型定义为@interface, 所有的Annotation 会自动继承java.lang.Annotation这一接口,并且不能再去继承别的类或是接口。
- 参数成员只能用public 或默认(default) 这两个访问权修饰。
- 参数成员只能用基本类型byte、short、char、int、long、float、double、boolean八种基本数据类型和String、Enum、Class、annotations等数据类型,以及这一些类型的数组。
- 要获取类方法和字段的注解信息,必须通过Java的反射技术来获取 Annotation 对象。
Q:MyBatis-plus如何实现分页功能?
A:用组件和SQL范围查询语句来返回数据。
【查找资料及补充】
1)导入Mybatis-plus的启动器
2)配置分页拦截器
@Configuration // 注解类为配置类 @MapperScan("org.example.mapper") // 扫描Mapper接口包路径 public class MyBatisConfig { @Bean // 把方法返回值对象mybatisPlusInterceptor注入spring容器 public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 向Mybatis过滤器链中添加分页拦截器 interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); return interceptor; } }
4、分布式数据库相关问题
Q:(举了之前西安做核酸时,健康码崩溃事件的例子)崩溃原因是什么?
A:客户太多导致服务器崩溃
Q:解决措施?
A:采用分布式的服务器,降低每台服务器的压力
【查找资料及补充】可以用负载均衡。
负载均衡,是指将负载(工作任务)进行平衡、分摊到多个操作单元上进行运行,从而协同完成工作任务。
负载均衡构建在原有网络结构之上,它提供了一种透明且廉价有效的方法扩展服务器和网络设备的带宽、加强网络数据处理能力、增加吞吐量、提高网络的可用性和灵活性。
服务器崩溃的几种原因:
第一:高并发流量或请求超过服务器承受力
第二:磁盘空间不足
第三:服务器超载
第四:服务器遭到恶意攻击
Q:分布式数据库如何保证数据的一致性?
A:没答上来……
【查找资料及补充】
经典方案 - eBay 模式
将需要分布式处理的任务通过消息日志的方式来异步执行。消息日志方案的核心是保证服务接口的幂等性。
例:如果产生了一笔交易,需要在交易表增加记录,同时还要修改用户表的金额。这两个表属于不同的远程服务,所以就涉及到分布式事务一致性的问题。
解决方法:将主要修改操作以及更新用户表的消息放在一个本地事务来完成。同时为了避免重复消费用户表消息带来的问题,达到多次重试的幂等性,增加一个更新记录表 updates_applied 来记录已经处理过的消息。
在第一阶段,通过本地的数据库的事务保障,增加了 transaction 表及消息队列。
在第二阶段,分别读出消息队列(但不删除),通过判断更新记录表 updates_applied 来检测相关记录是否被执行,未被执行的记录会修改 user 表,然后增加一条操作记录到 updates_applied,事务执行成功之后再删除队列。
通过以上方法,达到了分布式系统的最终一致性。
5、Java相关问题
Q:线程池的概念
A:说了线程池和JVM相关(联想到常量池)
#(可能的)正确答案:线程池 用于管理线程/是一种多线程处理模式,可以(1)降低线程创建和销毁的开销,(2)提高响应速度,(3)方便管理
Q:新建的线程放在哪里?
A:没答上来……
#(可能的)正确答案:
线程私有空间:程序计数器,虚拟机栈,本地方法栈。
线程共享空间: 堆、方法区。
Q:线程池如果满了,会有什么后果?
A:会阻塞,创建失败
【查找资料及补充】
线程的创建与销毁需要依赖操作系统,其代价是比较高昂的,频繁地创建与销毁线程对系统性能影响较大。出于线程管理的需要,线程池应运而生。线程池是一种多线程处理形式,处理过程中将任务提交到线程池,任务的执行交由线程池来管理。
当提交一个新任务,线程池的处理流程如下:
- 判断线程池中核心线程数是否已达阈值corePoolSize,若否,则创建一个新核心线程执行任务
- 若核心线程数已达阈值corePoolSize,判断阻塞队列workQueue是否已满,若未满,则将新任务添加进阻塞队列
- 若满,再判断,线程池中线程数是否达到阈值maximumPoolSize,若否,则新建一个非核心线程执行任务。若达到阈值,则执行线程池饱和策略。
当线程池的任务缓存队列已满 并且 线程池中的线程数目达到maximumPoolSize,如果还有任务到来,就会采取任务拒绝策略(线程池饱和策略)。
拒绝策略分为以下几种:
- ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出抛出RejectedExecutionException异常,默认策略
- ThreadPoolExecutor.DiscardPolicy:直接丢弃任务,不抛出异常
- ThreadPoolExecutor.DiscardOldestPolicy:抛弃下一个将要被执行的任务(队列最前面的任务),然后重新尝试执行任务(重复此过程)
- ThreadPoolExecutor.CallerRunsPolicy:由调用线程(主线程)处理该任务
Q:用过哪些Java开发模式?
A:代理模式,工厂模式
【查找资料及补充】设计模式分为三大类:
一,创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
二,结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
三,行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
其实还有两类:并发型模式和线程池模式。
反问环节
工作中常用的技术有哪些?
微服务技术、SpringCloud,dubbo(阿里开源的分布式RPC框架)
中间件、消息中间件,消息队列MQ
Redis缓存数据库
【更新】复试挂了
#你的秋招进展怎么样了#