阿里 P7 面试题 答案
Java多线程
1、线程池的原理,为什么要创建线程池?
答:1)线程池可以降低创建和销毁线程时的资源消耗,提高响应速度,提高现成的可管理性。
2)线程池构造参数:
corePoolSize:核心线程数
maximumPoolSize:最大线程数
keepAliveTime:空闲时间
unit:空闲时间单位
workQueue:任务等待队列。ArrayBlockingQueue(有界);SynchronousQueue(容量为1);LinkedBlockingQueue(无界)
threadFactory:线程工厂
handler:任务拒绝策略。丢弃并抛异常(默认策略);丢弃但不抛异常;丢弃最前面的任务;由调用线程处理该任务
3)几个参数之间的关系。corePoolSize>workQueue>maximumPoolSize>reject
2、线程的生命周期,什么时候会出现僵死进程;
答:1)new -> runnable -> running -> block -> dead
2)两个线程相互等待对方释放锁时,会出现僵死现象
3、什么是现线程安全,如何实现线程安全;
答:1)多线程并发访问共享资源时,能保证结果正确
2)可通过阻塞同步(加锁);非阻塞同步(CAS);避免共享资源(session、threadLocal)
4、java线程池如何合理配置核心线程数?
答:1)获取CPU核数。Runtime.getRuntime().availableProcessors()
2)分析程序属于CPU密集型还是IO密集型?
CPU密集型,核心线程数=CPU核数+1。减少花在任务切换上的时间
IO密集型,核心线程数=CPU核心数*2。线程越多,CPU利用率越高
5、synchronized、volatile区别、synchronized锁粒度、模拟死锁场景、原子性与可见性;
答: 1)死锁产生的条件:
互斥条件;环路等待;保持条件;不剥夺条件
2)synchronized锁粒度:无锁、偏向锁、轻量锁、重量锁
JVM相关
1、JVM内存模型
答:1)内存划分:堆、栈(java、本地)、方法区、计数器。方法区存放类信息、静态变量、常量、运行时常量池;堆主要放数组、对象、字符串常量池;栈是方法运行过程的内存模型。
方法区和堆都是线程共享的,栈和计数器是线程数有的。
2)JVM内存模型,和Java虚拟机运行时区域有关;JAVA内存模型是JAVA并发编程有关。
3)JAVA内存模型:主存(变量) -> 本地内存(变量副本) -> CPU(使用)
4)缓存一致性协议:
5)工作内存与主内存交互:
lock(锁定) -> read(读取) -> load(载入) -> use(使用) -> assign(赋值) -> store(存储) -> write(写入) -> unlock(解锁)
6)内存屏障(Memory barrier):是一种CPU指令,可以让CPU在内存访问上有序,保证屏障之前的指令会先于屏障之后的指令执行,用于控制特定条件下的重排序和内存可见性问题
7)指令重排序:为提高效率,程序在运行时内存实际的访问顺序和程序代码编写的访问顺序不一定一致
2、JVM里的有几种classloader,为什么会有多种?
答:BootstrapClassLoader -> ExtensionClassLoader -> AppClassLoader -> UserDefinedClassLoader
1)BootstrapClassLoader,负责加载<JAVA_HOME>/lib下的class,开发者不可以直接使用
2) ExtensionClassLoader,负责加载<JAVA_HOME>/lib/ext下的class,开发者可以直接使用
3)AppClassLoader,负责加载用户的class
3、java类加载机制、亲委派机制、双亲委派模型的好处?
答:1)类加载的几个阶段:加载、连接(验证、准备、解析)、初始化、使用、卸载。加载的目的是为了获取该类的二进制流
2)双亲委派:如果一个类加载器收到一个类加载的请求,会先将该请求委托给父级类加载器去加载,每一层都是如此。只有父类反馈无法完成这个加载请求时(它的搜索范围内找不到这个类),才会向下委托给子类加载器去加载。
3)双亲委派的好处:自己写的String.java不会覆盖系统的String.java,进而保护系统内部代码。
4、什么情况下我们需要破坏双亲委派模型;
答:1)Tomcat的WebAppClassLoader只会加载自己目录下的class文件,不会交给父类。因为一个Tomcat可以同时装载多个webapp,可防止jar包冲突
2)根据类加载机制,当被装载的类引用了另外一个类的时候,虚拟机就会使用装载第一个类的类装载器装载被引用的类。JDBC的Driver接口定义在JDK中,DriverManager也在JDK中,Driver实现类则在各厂商的实现包中,需要子类去加载。
5、常见的JVM调优方法有哪些?可以具体到调整哪个参数,调成什么值?
答:1)给新生代合理的空间,尽量避免新对象直接进入到老年代
2)大对象进入老年代,减少新生代对大对象的GC。 -XX:PretenureSizeThreshold 设置大对象直接进入老年代的阀值
3)设置对象进入老年代的年龄。-XX:MaxTenuringThreshold:默认值是15
6、什么时候触发FullGC?什么时候触发MinorGC(YoungGC)?
答:1)主动调用System.gc()
2) 老年代不足、持久代不足
3) YoungGC出现promotion failure
4)稳定对大小。设置 -Xmx 和 -Xms 一样的值。
7、JVM垃圾收集算法、垃圾收集器、class文件结构是如何解析的
答:1)垃圾回收算法:
a) 标记-清除算法:分成标记阶段(将要回收的做标记)和清除阶段(将标记的清除)。优点:简单易实现。缺点:碎片多,导致大对象空间不足触发垃圾回收。
b) 标记-整理算法:将内存划分为大小相等的两块,标记并复制到另一块区域。优点:内存利用率高。缺点:空间占用大;如果存活对象很多,复制效率低下。
c) 复制算法:将存活的对象复制到另一个区域
d) 分代收集算法:根据对象生命周期划分为多个区域,新生代(Eden8、Survivor1:1,复制算法)、老年代(标记整理)、永久代。
8、CMS回收机制
答:1)初始标记,只标记与“根”直接关联的对象,此时会Stop the World
2)并发标记,
3)并发预清理
4)重新标记
5)并发清理
6)重新标记
Java扩展
1、红黑树的实现原理和应用场景;
2、NIO是什么?适用于何种场景?
3、Java9比Java8改进了什么;
答:模块化(rt.jar解散开来)、接口私有方法、HTTP2.0、增强Stream
4、HashMap内部的数据结构是什么?底层是怎么实现的?
答:loadFactory:负载因子,默认0.75,槽位占到此比例时,开始扩容,扩容是对数组扩容,长度增长一倍,将源数组保存的数据进行rehash后,放入新数组中。
节点组成:Entry包含Key,Value,Next,hash值几个字段
数组+链表:数组是HASH槽位,通过Entry的next指向下一个节点,形成链表。
5、说说反射的用途及实现,反射是不是很慢,我们在项目中是否要避免使用反射;
答:1)调用对象、调用方法、使用字段等
2)Class.forName("xxxxx.class")方法会比较慢,可将此方法放到for循环外面
3)调用方法前,使用method.setAccessible(true)跳过安全检查,可提高方法调用效率
6、说说自定义注解的场景及实现;
答:1)运行时,靠反射获取注解。如在AOP中获取注解,或在filter中获取注解
2)应用场景:权限、日志、登录、缓存
7、Arraylist、LinkedList、Vector的 区别;
答:1)Vector是通过数组实现的,线程同步,只允许一个线程写数据,效率比ArrayList低
2)ArrayList是通过数组实现的,线程异步,适合随机访问,不适合频繁插入、删除元素
3)LinkedList是通过链表实现,适合频繁插入、删除场景,但随机访问效率低
Spring
1、Spring AOP的实现原理和场景;(应用场景很重要)
2、Spring bean的作用域和生命周期;
3、Spring Boot比Spring做了哪些改进?Spring 5比Spring4做了哪些改进;(惭愧呀,我们还在用Spring4,高版本的没关心过)
4、Spring IOC是什么?优点是什么?
5、SpringMVC、动态代理、反射、AOP原理、事务隔离级别;
中间件
1、Dubbo完整的一次调用链路介绍;
答:1)调用方封装dubbo协议,包含请求头和请求体
2)调用方发起调用请求,交给InvokerInvocationHandler调用,最终通过netty的NioClientSocketChannel发送数据
3)服务方将请求解码
4)服务方将请求内容传递给NettyHandler,通过线程池中获取线程,进入服务调用逻辑
5)服务方返回调用结果,并对响应体进行编码
6)调用方接收响应结果,解码响应
2、Dubbo支持几种负载均衡策略?
答:1)随机策略
2)轮询策略
3)最少活跃调用数。耗时短的,被调用次数就多
4)一致Hash
3、Dubbo Provider服务提供者要控制执行并发请求上限,具体怎么做?
答:1)服务端控制。 <dubbo:service interface="com.foo.BarService" executes="10" />
2)客户端控制。<dubbo:reference interface="com.foo.BarService" actives="10" />
4、Dubbo启动的时候支持几种配置方式?
答:1)xml
2)注解
3)javaBean
4)properties文件
5、了解几种消息中间件产品?各产品的优缺点介绍;
答:1)Rabbit 集群不支持动态扩展,erlang语言编写,不利于源码查看
2)ActiveMQ 莫名其妙丢消息,后期维护较少,不适用于上千个队列的场景
3)RocketMQ 性能好,简单;新文档较少
4)Kafka 适用于日志领域
6、消息中间件如何保证消息的一致性和如何进行消息的重试机制?
答:1)生产者发送消息前,保证生产者本地的逻辑已经处理完成
2)消费者确认消息机制:自动确认、手动确认、无确认可被多次消费
3)一致性问题原因:生产者发送消息后,消费者接收到消息会自动确认,此时消费者挂掉了。此时就会存在生产者已处理、消费者未处理的不一致的问题。
4)如何处理消息不一致的问题?
a) 生产者再发一次消息。通过一张表来记录每个消息的发送状态,未处理完成的消息,会定时再发送(定时补偿)。消费者通过分布式锁,来保证消息不被重复消费
b) 消息者主动查询生产者消息是否结束
7、Spring Cloud 熔断、限流、降级;
答:1)降级。(可以在客户端[主动降级],也可在服务端[被动])
a) 降级处理策略:失败重连;直接返回友好提示;调用备用服务;返回缓存数据。
b) 降级回退方式:FailFast(快速失败);FailSilent(无声失败);......
2)限流。可放入网关中,通过过滤器实现。向令牌桶以恒定速度添加令牌,一个请求消耗一个令牌。令牌桶中的令牌数量大于0才可以访问,否则拒绝
3)熔断。熔断不等于宕机!熔断时,服务器还是有响应能力的,只是响应慢或暂无响应。
https://www.jianshu.com/p/b9af028efebb hystrix单独使用
数据库篇
1、锁机制介绍:行锁、表锁、排他锁、共享锁;
答:1)表级锁:开销小,加锁快;不会出现死锁;粒度大,发生锁冲突的概率最高,并发度最低。
2)页级锁:介于表级锁和行级锁之间
3)行级锁:开销大,加锁慢;容易出现死锁;粒度小,发生锁冲突的概率最低,并发度最高。
2、乐观锁的业务场景及实现方式
3、事务介绍,分布式事物的理解,常见的解决方案有哪些,什么事两阶段提交、三阶段提交;
4、MySQL记录binlog的方式主要包括三种模式?每种模式的优缺点是什么?
5、MySQL锁,悲观锁、乐观锁、排它锁、共享锁、表级锁、行级锁;
6、分布式事务的原理2阶段提交,同步\异步\阻塞\非阻塞;
7、数据库事务隔离级别,MySQL默认的隔离级别、Spring如何实现事务、
8、JDBC如何实现事务、嵌套事务实现、分布式事务实现;
9、SQL的整个解析、执行过程原理、SQL行转列;
Redis
1、Redis为什么这么快?redis采用多线程会有哪些问题?
2、Redis支持哪几种数据结构;
3、Redis跳跃表的问题;
4、Redis单进程单线程的Redis如何能够高并发?
5、Redis如何使用Redis实现分布式锁?
6、Redis分布式锁操作的原子性,Redis内部是如何实现的?
Tomcat
1、Tomcat类加载机制
答:1)Tomcat不遵循双亲委派模型;
2)隔离性。同一个Tomcat可同时装载不同版本的jar包,互不影响
2、Tomcat架构
答:Server >> Service >> *Connector & Container >> Host/Engine/Context
技术四面面试题如下
一面(问了数据结构、jvm、锁等):
HashMap底层如何实现?
Hash一致算法?
说说HashMap和ConcurrentHashMap的区别?treemap和HashMap的区别?
java的内存分区?
java对象的回收方式,回收算法?
CMS和G1了解吗?
CMS解决什么问题,说一下回收的过程?
CMS回收停顿了几次?
java栈什么时候会内存溢出,java堆呢,说一种场景?
集合类如何解决这个问题(软引用和弱引用),讲下这个两个引用的区别?
java里的锁了解哪些?
synchronized锁升级的过程(偏向锁到轻量锁再到重量级锁),分别如何实现的,解决的是哪些问题?
Tomcat的基本架构是什么?
什么是类加载器?
说说双亲委派模型机制?
GC的机制是什么?GC算法和回收策略?
二面(线程、数据库、缓存、协议等):
线程池由哪些组件组成?
有哪些线程池,分别怎么使用?拒绝策略有哪些?
什么时候多线程会发生死锁,写一个例子?
Redis的数据结构是什么?线程模型说一下?
讲讲Redis的数据淘汰机制?
说说Redis的数据一致性问题?
Redis的分布式怎么做?
RPC讲一下?
三次握手和四次挥手?如果没有三次握手有问题吗?
Http请求过程,DNS解析的过程?
InnoDB支持的四种事务隔离级别名称是什么?有什么区别?说说MySQL隔离级别?
事务的特性及慢查询?
BTree机制说一下?
说说MySQL常用的优化方法?
三面(分布式,消息队列等):
cap了解吗,分别指什么?
强一致性和弱一致性有什么方法来实现的?
负载均衡怎么实现?为什么这么做?
缓存雪崩说下?
MySQL主从复制怎么实现的?具体原理是什么?有什么优缺点?
讲讲分布式事务?
消息队列,用到什么场景(削峰,限流,异步)?
zk的性能瓶颈怎么克服?
讲了下kafka,怎么保证数据不丢失?确保消息不会重复消费?
消息送达确认是怎么实现的?