真实面试系列-万泰建设Java面试(2021年04月25日)

1、公司介绍

在这里插入图片描述


2、应聘职位介绍

在这里插入图片描述


3、面试流程

  1. 简单自我介绍一下
  2. 他提问环节
  3. 我提问环节

3.1、自我介绍

       主要介绍了,我的工作经验年限,做过什么项目,最近在什么项目,最近这个项目的背景,使用到了哪些技术栈。


3.2、他提问环节

  1. 简单介绍一下springboot的自动装配?
    答:在spring-boot的核心注解SpringBootApplication里,有3个注解@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan。其中@EnableAutoConfiguration的意义是启动自动配置,里面有一个选择器AutoConfigurationImportSelector.class,去JAR包META-INF中可以找到spring.factories。
  2. 说一下ArrayList和LinkedList的区别?他们是不是线程安全的?ArrayList对应的线程安全的类是哪一个?
    答:ArrayList:底层实现是数组,查询很快,插入,删除慢,每次扩容原来的1.5倍,LinkedList:底层实现是链表,查询慢,插入,删除快。他们都不是线程安全的。ArrayList的同步容器:Collections.SynchronizedList(),并发容器:CopyOnWriteArrayList
  3. 说一下Java的三大特征,说一下你对多态的理解?
    答:封装,继承和多态,多态:即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。比如:3个杯子里面都装有酒,只有喝了才知道这三个杯子里面装的什么酒,这三个都是酒的子类,我们只是通过酒这一个父类就能够引用不同的子类,这就是多态。
  4. 说一下continue和break的区别?
    答:continue:
    1.continue 语句中断循环中的迭代,如果出现了指定的条件,然后继续循环中的下一个迭代。
    2.continue所在的循环体并没有结束。
    break:
    1.break 语句可用于跳出循环。
    2.break所在的循环体已经结束。
    在这里插入图片描述
for (i=0;i<5;i++){
	if (i==3) break;
	x=x + "The number is " + i + "<br>";
}
//	只输出 0 , 1 , 2 , 到3就跳出循环了
	
for (i=0;i<=5;i++){
	if (i==3) continue;
		x=x + "The number is " + i + "<br>";
}
//	不输出3,因为continue跳过了,直接进入下一个迭代
  1. 说一下死锁是怎么造成的?
    答:Java发生死锁的根本原因是:在申请锁时发生了交叉闭环申请.即线程在获取了锁A,但是并没有释放它,而又去申请了锁B,但是锁B已经给另一个线程获取了,在释放锁B之前又要获得锁A,因此发生了闭环,陷入了死锁循环.
public static void main(String[] args) {
    final Object a = new Object();
    final Object b = new Object();
    Thread threadA = new Thread(() -> {
        synchronized (a) { //sleep 下可以确保死锁
            System.out.println("now i in threadA-locka");
            synchronized (b) {
                System.out.println("now i in threadA-lockb");
            }
        }
    });
    Thread threadB = new Thread(() -> {
        synchronized (b) { //sleep 下可以确保死锁
            System.out.println("now i in threadB-lockb");
            synchronized (a) {
                System.out.println("now i in threadB-locka");
            }
        }
    });
    threadA.start();
    threadB.start();
}

       如何避免:最简单的就是不使用锁,然后就是几个功能不要使用同一把锁,然后就是超时放弃锁。

  1. 说一下mysql的优化方式有哪些?用过全连接吗?
    答:只要优化的有两个方面:安全和性能。安全的话,就是保证数据持续性,性能就是数据的高性能访问。优化方向有:硬件,系统 ,应用,数据库,架构(高可用、读写分离、分库分表),硬件的话就是CPU,内存和存储,网络等;系统:主要是设置网络和IO的参数;应用:数据库应用和业务应用独立;数据库:数据库的参数有话,比如缓存和线程参数,连接层面的设置,存储引擎上的参数优化。SQL设计层面的优化:1、选取最适用的字段属性(NOTNULL,尽量短,尽量数字);2、使用join来代替子查询;3、使用联合(UNION)来代替手动创建的临时表;4、事务;5、锁定表;6、使用外键;7、使用索引;8、优化的查询语句
    在这里插入图片描述
  2. 简单介绍一下使用redis分布式锁?
    答:使用setnx进行加锁,如果key不存在就认为已经被获取了,,expire设置加锁时间,value使用唯一标识。
  3. 简单介绍一下分布式事务?你们公司是怎么实现分布式事务的?
    答:分布式事务的最常见的决绝方案有三种:两阶段(效率低,同步阻塞),TCC(代码侵入性太大),基于消息的最终一致性(成本很高)。将本地操作和发送消息放在一个事务中,保证本地操作和消息发送要么两者都成功或者都失败。下游应用向消息系统订阅该消息,收到消息后执行相应操作。如果执行失败,进行重试补偿。
  4. 说一下你工作中用到了那些springcloud的组件?nacos的配置文件和服务是如何关联的?bootstrap.yml中的nocas配置是怎么样的?
    答:nacos:注册和配置中心;sentinel:流量监控,降级限流,熔断,网关;openFeign:服务之间的调用;网关:gateway等。一般的建议是使用命名空间来隔离服务;namespase(命名空间),文件名,nacos地址,文件类型等
  5. 简单介绍一下spring的特性?aop的实现原理?说一下你对动态代理的理解?说一下jdk 的代理和cglib实现代理的区别?
    答:Spring是轻量级框架,有两个特别牛逼的功能:IOC和AOP;IOC就是对象交给bean进行管理,我们不用关心对象的生成,只需要使用。AOP把核心业务和组件代码分离,主要是通过Java的动态代理实现。那么以拍电影举个栗子:
1.前期筹备,剧本确定、演员试镜确定
############分割线a
13. 开拍、剪辑、制作
############分割线b
14. 营销、宣传、公映

       1->2->3这个流程是拍电影的业务流程,但是如果我要拍花絮怎么办,这个流程不属于现在的电影业务流程,我们需要安排一个零时的业务,那我们就要在 ############分割线a 分割线那里添加摄花絮的计划,分配一些人员。
       1、Jdk动态代理:利用拦截器(必须实现InvocationHandler)加上反射机制生成一个代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理
       2、 Cglib动态代理:利用ASM框架,对代理对象类生成的class文件加载进来,通过修改其字节码生成子类来处理

  1. 说一下spring的事务传播机制?和事务隔离级别?A中开启事务,调用B,B中存在事务吗?@Transactional的使用
    答:
    保证同一个事务中
           PROPAGATION_REQUIRED 支持当前事务,如果不存在 就新建一个(默认)
           PROPAGATION_SUPPORTS 支持当前事务,如果不存在,就不使用事务
           PROPAGATION_MANDATORY 支持当前事务,如果不存在,抛出异常
    保证没有在同一个事务中
           PROPAGATION_REQUIRES_NEW 如果有事务存在,挂起当前事务,创建一个新的事务
           PROPAGATION_NOT_SUPPORTED 以非事务方式运行,如果有事务存在,挂起当前事务
           PROPAGATION_NEVER 以非事务方式运行,如果有事务存在,抛出异常
           PROPAGATION_NESTED 如果当前事务存在,则嵌套事务执行
    设置事务隔离级别(5种)
           未提交读(read uncommited) :脏读,不可重复读,虚读都有可能发生
           已提交读 (read commited):避免脏读。但是不可重复读和虚读有可能发生
           可重复读 (repeatable read) :避免脏读和不可重复读.但是虚读有可能发生.
           串行化的 (serializable) :避免以上所有读问题.
    A.a() B.b()的事务配置 a()没有事务的结果 a()有事务的结果
           REQUIRED b()创建自己的事务; b()接受a()的事务
           SUPPORTS b()不创建自己的事务; b()接受a()的事务
           MANDATORY b()报异常 b()接受a()的事务
           NESTED b()创建自己的事务; b()接受a()的事务,成为a()嵌套的子事务
           NEVER b()不创建自己的事务; b()报异常
           REQUIRES_NEW b()创建自己的事务; b()不接受a()的事务,b()先执行,内层事务失败不会影响外层事务
           NOT_SUPPORTED b()不创建自己的事务; b()不接受a()的事务,b()先执行
    @Transactional使用
           @Transactional(propagation=Propagation.REQUIRED) //控制事务传播。默认是Propagation.REQUIRED
           @Transactional(isolation=Isolation.DEFAULT) //控制事务隔离级别。默认跟数据库的隔离级别相同
           @Transactional(readOnly=false) //控制事务可读写、只可读。默认可读写
           @Transactional(timeout=30) //控制事务的超时时间,单位秒。默认跟数据库的事务控制系统相同
           @Transactional(rollbackFor=RuntimeException.class) //控制事务遇到哪些异常会回滚。默认是RuntimeException
           @Transactional(rollbackForClassName=RuntimeException) //同上
           @Transactional(noRollbackFor=NullPointerException.class) //控制事务遇到哪些异常不会回滚。默认遇到RuntimeException回滚
           @Transactional(noRollbackForClassName=NullPointerException)//同上

  2. 说一下你们项目的层级?
    答:config,dao,model,service,controller,util,annotation,constant,exception,enums,aspectj,intercptor,manager

  3. contrller层能不能调用dao?
    答:可以,如果没有业务逻辑也可以直接调。

  4. 说一下docker的几个常用命令?
    答:docker search:查找镜像,docker pull:拉取容器,docker run:运行容器,docker exec 进入容器,docker ps 查看运行中的容器,docker log 查看容器运行的日志。

  5. 说一下linux下如何查询进程?说一下 top 和ps 的区别?
    答:top -c 和 ps ,top可以查找出老的进程占CPU的比从大到小。

  6. 说一下JVM的结构?说一下年轻代数据如何到达老年代的?说一下各个阶段的回收策略?说一下回收算法?说一下有几种垃圾回收器?详细介绍一下CMS和G1的原理和流程?说出一些常用的JVM参数?常见的JVM优化?
    答:
    1、类加载器(ClassLoader):Java 代码转换成字节码,类的加载机制:加载 ,验证,准备,解析,初始化,使用,卸载
    运行时数据区(Runtime Data Area):把字节码加载到内存中
    执行引擎(Execution Engine):字节码翻译成底层系统指令,交由 CPU 去执行,而这个过程中需要调用其他语言的本地库接口来实现整个程序的功能
    本地库接口(Native Interface)
    2、对象活够15岁就如老年代,对象足够大,Minor GC后仍然存活的情况
    3、引用计数法(+1 -1 0),可达性分析法(gc roots:有无引用)
    4、标记 - 清除算法(标记无用的),标记 - 整理算法(把空闲的空间上移),复制算法(复制到新的空间),分代算法(交替清空)
    5、Serial收集器(单线程收集器),Serial-Old收集器(老年代),ParNew收集器(多线程版本),Parallel Scavenge收集器(缩短垃圾回收时间),Parallel Old收集器(老年代),CMS收集器(最短回收停顿时间:标记-清除法),G1收集器(标记-整理算法,可预测停顿)。
    6、CMS收集器:(1)初始标记:只标记根节点直接关联的引用对象(GC Roots),需要暂停用户线程(时间短);
    (2)并发标记:标记其他引用对象,可以跟用户线程并发同时执行;
    (3)重新标记:暂停用户线程,对并发标记期间新增加的引用关系变化再次标记(时间短);
    (4)并发清除:跟用户线程并发进行。
    G1收集器:将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔阂了,它们都是一部分可以不连续 Region 的集合。
    7、-Xmx -Xms:这个就表示设置堆内存的最大值和最小值。这个设置了最大值和最小值后,jvm启动后,并不会直接让堆内存就扩大到指定的最大数值。而是会先开辟指定的最小堆内存,如果经过数次GC后,还不能,满足程序的运行,才会逐渐的扩容堆的大小,但也不是直接扩大到最大内存。
    -Xmn:设置新生代的内存大小。
    -XX:NewRatio:新生代和老年代的比例。比如:1:4,就是新生代占五分之一。
    -XX:SurvivorRatio:设置两个Survivor区和eden区的比例。比如:2:8 ,就是一个Survivor区占十分之一。
    -XX:+HeapDumpOnOutMemoryError:发生OOM时,导出堆的信息到文件。
    -XX:+HeapDumpPath:表示,导出堆信息的文件路径。
    -XX:OnOutOfMemoryError:当系统产生OOM时,执行一个指定的脚本,这个脚本可以是任意功能的。比如生成当前线程的dump文件,或者是发送邮件和重启系统。
    -XX:PermSize -XX:MaxPermSize:设置永久区的内存大小和最大值。永久区内存用光也会导致OOM的发生。
    -Xss:设置栈的大小。栈都是每个线程独有一个,所有一般都是几百k的大小。
    8、新生代尽量设置大一些,让对象在新生代多存活一段时间,每次Minor GC 都要尽可能多的收集垃圾对象,防止或延迟对象进入老年代的机会,以减少应用程序发生Full GC的频率。
    设置堆的最大值和最小值,防止收缩堆消耗时间
    避免大对象和大数组,直接进入老年代,
    大量数据进行分批处理
    使用完集合进行晴空

  7. CI和CD的区别?
    答:CI:持续集成,开发人员将会频繁的提交代码到主干。这些新提交在最终合并到主线之前,都需要通过编译和自动化测试流进行验证。这样做是基于之前持续集成过程中很重视自动化测试验证结果,以保障所有的提交在合并主线之后的质量问题,对可能出现的一些问题进行预警。
    CD:持续交付:自动化的发布流,以及通过一个按键就可以随时随地实现应用的部署上线。
    CD:持续部署:通过这个方式,任何修改通过了所有已有的工作流就会直接和客户见面。没有人为干预(没有一键部署按钮),只有当一个修改在工作流中构建失败才能阻止它部署到产品线。

  8. 说一下你在开发过程中遇到最难的问题?是怎么解决的?
    答:解决幂等性问题,我们引入了乐观锁来解决这个问题,基于CAS的原理。在数据库表中加入version字段。

3.3、我提问环节

  1. 公司的业务是做什么?
  2. 公司用的技术栈是哪一些?
  3. 公司的人员配置怎么样?

4、往期佳文

4.1、面试系列

1、吊打面试官之一面自我介绍
2、吊打面试官之一面项目介绍
3、吊打面试官之一面系统架构设计
4、吊打面试官之一面你负责哪一块
5、吊打面试官之一面试官提问
6、吊打面试官之一面你有什么问题吗

······持续更新中······

4.2、技术系列

1、吊打面试官之分布式会话
2、吊打面试官之分布式锁
3、吊打面试官之乐观锁
4、吊打面试官之幂等性问题
5、吊打面试关之分布式事务
6、吊打面试官之项目线上问题排查

······持续更新中······

4.3、源码系列

1、源码分析之SpringBoot启动流程原理
2、源码分析之SpringBoot自动装配原理
3、源码分析之ArrayList容器
4、源码分析之LinkedList容器
5、源码分析之HashMap容器
6、源码分析之ConcurrentHashMap容器
7、源码分析之五种Map容器的区别

······持续更新中······

4.4、数据结构和算法系列

1、数据结构之八大数据结构
2、数据结构之动态查找树(二叉查找树,平衡二叉树,红黑树)
3、算法系列之十大经典排序算法

······持续更新中······

4.5、并发系列

1、并发系列之初识多线程
2、并发系列之JMM内存模型
3、并发系列之synchronized解析
4、并发系列之volatile解析
5、并发系列之synchronized与volatile的区别
6、并发系列之Lock解析
7、并发系列之synchronized与lock的区别
8、并发系列之CAS与原子操作
9、并发系列之AQS分析
10、并发系列之线程池解析
11、并发系列之锁的知识梳理

······持续更新中······

4.6、面试题系列

1、面试题系列之并发面试题
2、面试题系列之网络面试题
3、面试题系列之IO面试题
4、面试题系列之消息队列面试题

······持续更新中······

4.7、JVM系列

1、JVM系列之JVM介绍
2、JVM系列之Class文件解析
3、JVM系列之Java 类加载机制
4、JVM系列之JVM内存结构

······持续更新中······


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值