(1)面试总结
蘑菇街总结
分布式锁,秒杀系统,避免重复下单,反射,zookeeper注册原理,数据库事务,数据库锁,mybatis,spring aoc底层实现,中间件的区别,怎么选型,linux gc命令等,算法题(复杂问题简单化)
京东金融总结
队列实现原理,jvm,gc算法原理,为什么用复制算法,多线程锁的种类,读写锁,hashtable原理,spring 和内存动态装配,四次握手断开连接,类的加载,线程池延时原理,volatile底层原理,公平锁和非公平锁
网易二面
人脸识别算法实现(考察知识的广度) 设计一个分布式存储系统(考验架构能力,需求把握,问题拆解,头脑风暴,具体实现) spring新特性 面试能力
阿里面试
1你理解的session是什么
2我们系统中http序列化怎么做的
3spring cloud和dubbo的区别
4dubbo之间的相互依赖
5kafka为什么性能这么好
6hibernate不好的地方
7hibernate管理的对象的状态
8一致性hash算法
9锁的区别 Synchronized和lock的区别,底层实现
10 gcroot的理解
11 并发内存模型jmm
12 栈的作用
13 Main Memory和Working Memory
14 线程池提交第二个任务会用显示加载的线程吗
15 hashcode作用
16 两个整型变量不通过第三个变量交换数据
1基本功 2知识视野,主动性不够,学习相关联 3要有不断改进的精神,保证稳定性的同时不断优化 4学习要往底层学习,你的问答还很粗糙,gcroot和lock的实现还很粗糙 5程序员职业生涯还很长,继续努力把,你挂了
(2)提纲
网络 http和socket spring(事物)bean scope + nio + 数据库事物 缓存 消息队列 多线程(volatile)线程池 lock 分布式事物 算法 分布式锁 设计模式 jvm 算法
spring springboot redis websocket 算法(常见排序算法) 设计模式 JAVA序列化 nio dubbo spring cloud
tomcat集群 tomcat加载基本流程 Spring基本流程 SpringMVC基本流程 Mybatis原理 Mybatis和Hibernate的区别 设计模式在spring中的使用
jvm参数、调优 同步器 cas原理 sql springbean单例多例 java中的类加载器 hashcode equal sql
事物 spring
netty session和cookie的生命周期以及它们之间的关联 反向代理 分布式存储系统
cglib比jdk动态代理快
spring如何两条数据库操作获得线程池里的同一个线程 theadlocal
Hibernate一级缓存
数据库调优
sql实现悲观锁和乐观锁
aop 切面传递 内部调用不触发aop逻辑
session和cookies区别
tomcat类加载机制 反双亲委派模型
struts和spring mvc的区别
Eureka和zookeeper的区别,dubbo和spring cloud的区别
基础,Integer,String == 手写单例模式 算法
序列化和反序列化
泛型,泛型擦除
(3)基础
两个方法完全相同不能重载,不同种类的参数顺序不同可以重载
list以顺序存储数据 set无序不含重复数据 hashset用了hashmap的key存数据来实现
ArrayList用了数组,LinkedList用了链表
StringBuffer线程安全StringBuilder线程不安全。
8种基础数据类型 byte(1个字节) short(2) int(4) long(8) float(4) double(8) char(2) boolean
4种引用类型 强引用(不会回收) 软引用(内存不足回收) 弱引用(直接回收) 虚幻引用
HashMap中键值允许为空 线程不安全 Hashtable中键值不允许为空 方法直接加锁 线程安全
ConcurrentHashMap 16个Segment 分段锁 读不加锁(volatile)next final保证访问后续连接不会被改变 不允许用null作为键和值被认为发生了重排序
ConcurrentLinkedQueue线程安全队列
== 判断两个对象是否指向同一个引用,比较的是堆内存中的地址;而equals比较“内容”是否一致。
hashmap 在1.8中默认初始容量是16,加载因子是0.75,容量为2的n次幂,链表元素达到8时,链表结构转化成红黑树结构 链表小于6还原为链表 null hash为0 储存在0位置
hash码算索引h&(length-1) 红黑数平均查找长度为log(n) 8为3 链表是6/2=3
file io阻塞io
string hashcode h=31*h+val[i] 31素数 占5bits
字符流和字节流的区别 字符流用到了缓冲区 大小问题,汉字只能字符流 字节不用close,字符需要
排序算法
插入排序 已排序好序列,取数从该序列最后一个遍历插入
希尔排序 下标差k排序 K=k/2排序 k=1插入排序
选择排序 遍历获得最小放在前面
堆排序 大根堆 根节点大于左右子数
冒泡排序 每次把最大的放最后
快速排序 选择第一个数,小于放左边,大于放右边
归并 每次相邻两个组成有序
基数排序 按位排序
(4)jvm
java内存模型
java栈(线程私有存储局部变量,操作栈和方法返回值等)
本地方法栈(native方法服务)
程序计数器(线程执行行号指示器)
堆(新生代,老年代 分配对象实例)
方法区(永久代 加载的类信息,常量,静态变量,即时编译代码)
新生代(一个较大的eden和 from survivor ,to survivor 8:1:1复制算法 10/100空间浪费,98/100可回收) 新生代存活对象大于survivor大小进入老年代
老年代 (标记清除/标记整理)
永久代 (方法区 包含运行时常量池)
到达15岁进入老年带,相同年龄对象大于survivor区大小一半,大于该年龄进入老年代
类加载的五个过程 加载,验证,准备,解析,初始化
对象的创建
new指令,运行时常量池定位类的符号应用,没有则加载 内存规整指针碰撞,内存不规整空闲列表 cas或tlab分配(内存分小块)
对象基本信息(是那个类的实例,gc年龄等)
对象访问定位
句柄,存在句柄池,java栈指向句柄地址,句柄包含实例地址和类型地址
直接指针,java栈指向对象实例数据,对象实例包含指向类型的指针(hotsopt默认)
jvm调优工具 jconsole和visualvm 查看堆内存使用情况 dump可以查看死锁和内存泄露(类的实例和大小过大)
吞吐量大的应用,一般采用并行收集,开启多个线程,加快gc的速度。
响应速度高的应用,一般采用并发收集,比如应用服务器。
年老代建议配置为并发收集器,并发收集器可以压缩和整理磁盘碎片,
垃圾回收算法,引用计数 可达性分析 gc root起始向下搜索 没引用回收 是否有finalize方法标记一次放入f-queue低优先级 gc二次标记,有引用逃脱
Minor GC触发条件:当Eden区满时,触发Minor GC。每次对象+1岁,默认15岁进入老年代
Full GC触发条件:(1)调用System.gc时(2)老年代空间不足(3)永久代(方法区)空间不足
(4)通过Minor GC后进入老年代的平均大小大于老年代的可用内存
(5)对象转存到老年代,且老年代的可用内存小于该对象大小
垃圾回收器
cms 初始标记,并发标记,重新标记,并发清理
并发标记,低停顿 对cpu自资源敏感,无法处理标记过程的垃圾,标记清除带来空间碎片
g1 1、初始标记;2、并发标记;3、最终标记;4、筛选回收
并行并发,分代收集,空间整合(整体标记清理 局部复制 从两个Region之间看复制算法 提供规整的可用内存),
可预测停顿时间(使用Region划分内存空间,跟踪各Region垃圾堆积价值,维护优先列表,优先回收价值大的,提高效率) 记录标记过程变化 记录日志后合并,筛选回收
可以作为gc root的对象
虚拟机栈中的引用对象
方法区中类静态属性引用的对象
方法区中常量引用对象
本地方法栈中JNI引用对象
每个Java应用程序都有一个Runtime类实例,使应用程序能够与其运行的环境相连接。可以通过getRuntime方法获取当前运行时。 Runtime.getRuntime().gc()
(5)springs
BeanFactroy延迟加载注入bean ApplicationContext一次性创建bean
支持BeanPostProcessor BeanFactory需要手动注册,而ApplicationContext则是自动注册。
beanFactory主要是面对与 spring 框架的基础设施,Applicationcontex主要面对spring使用开发者,开发者使用
Spring AOP五种通知:前置通知,后置通知,返回通知,异常通知,环绕通知
依赖注入 反射
aop用了动态代理 静态代理AspectJ 动态代理:有接口JDK动态代理,没有接口CGLIB代理
CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。
Cglib动态代理执行代理方法效率之所以比JDK的高是因为Cglib采用了FastClass机制,它的原理简单来说就是:为代理类和被代理类各生成一个Class,这个Class会为代理类或被代理类的方法分配一个index(int类型)。
这个index当做一个入参,FastClass就可以直接定位要调用的方法直接进行调用,这样省去了反射调用,所以调用效率比JDK动态代理通过反射调用高。
过滤器Filter依赖于servlet容器 基于函数回调 对几乎所有请求起作用
拦截器Interceptor依赖于web框架 基于java反射,是aop的一种运用 只能对action起作用
过滤器包裹住servlet,servlet包裹住拦截器
注入方式 构造器注入,setter注入,注解注入
spring用到的设计模式 简单工厂 工厂模式 单例模式 适配器模式 包装器模式 代理模式 观察者模式 策略模式 模版方法
spring事务隔离级别
ISOLATION_DEFAULT
ISOLATION_READ_UNCOMMITTED(未提交读) 导致脏读
ISOLATION_READ_COMMITTED(提交读) 避免脏读,允许不可重复读和幻读
ISOLATION_REPEATABLE_READ(可重复读) 避免脏读,不可重复读,允许幻读
ISOLATION_SERIALIZABLE(序列化)串行化读,事务只能一个一个执行,避免了脏读、不可重复读、幻读。执行效率慢,使用时慎重
脏读:一事务对数据进行了增删改,但未提交,另一事务可以读取到未提交的数据。如果第一个事务这时候回滚了,那么第二个事务就读到了脏数据
不可重复读:一个事务中发生了两次读操作,第一次读操作和第二次操作之间,另外一个事务对数据进行了修改,这时候两次读取的数据是不一致的
幻读:第一个事务对一定范围的数据进行批量修改,第二个事务在这个范围增加一条数据,这时候第一个事务就会丢失对新增数据的修改。
Spring事务的传播属性
PROPAGATION_REQUIRED 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择,也是 Spring 默认的事务的传播。
PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。新建的事务将和被挂起的事务没有任何关系,是两个独立的事务,外层事务失败回滚之后,不能回滚内层事务执行的结果,内层事务失败抛出异常,外层事务捕获,也可以不处理回滚操作
PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY 支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED
如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行。它使用了一个单独的事务,这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager事务管理器起效
spring作用域:单例(整个应用只创建一个实例) 原型(每次注入创建新的实例) 会话 请求
(6)多线程
juc包主要包含原子操作,lock,Collections ,Executer ,Tools
线程状态 新建状态 就绪状态 阻塞状态 运行状态 死亡状态
sleep()不会放弃锁,wait()会放弃锁
Synchronized是非公平锁 1.6引入偏向锁 轻量级锁(自旋)重量级锁 jvm参数配置
锁优化 减小锁的范围 减小锁的粒度 锁分段 避免热点域(计算器分成多段相加) 放弃独占锁(读写锁 原子变量)
线程中断
线程转储分析死锁
轮询锁与定时锁解决死锁问题,不能请求全部的锁会主动释放
重入和读写锁,公平锁和非公平锁
乐观锁 认为读多,读不加锁,写根据版本号然后加锁写 cas
悲观锁 认为写多,读写均上锁
线程池
ThreadPoolExecutor基类 corePoolSize核心池的大小 maximumPoolSize线程池最大线程数
线程数小于corePoolSize,创建新线程执行任务,等于加入LinkedBlockingQueue 线程执行完会从队列中取任务
submit()有返回 execute()无返回
fixThreadPool正规线程 固定线程,无界队列
cachedThreadPool 缓存线程池 最大线程数很大 线程等待60s终止 使用没用容量的SynchronousQueue
singleThreadPoll 单线程线程池,无界队列
ScheduledThreadPoll 延迟执行,周期重复执行 非核心线程很大 独占式和共享式 DelayQueue
futuretask可以异步获取结果或取消执行
队列同步器AbstractQueuedSynchronizer(AQS)
两个节点,head和tail指向首节点和尾节点 基于cas设置尾节点 fifo
非公平锁,只有锁被某个线程持有时,新发出请求的线程才会被放入队列中,发出请求时锁空闲直接获得锁
重入锁ReentrantLock 公平锁和非公平锁 非公平锁性能远好于公平锁 计数器记录获取锁的次数,为0释放
读写锁ReentrantReadWriteLock 整形变量 高16位表示读,低16位表示写 写锁必须等读锁完全释放,为了数据可见性
读锁 支持重进入的共享锁 锁降级(写锁降级读锁)把持写锁获取读锁然后释放写锁 不支持锁升级
LockSupport park阻塞当前线程,unpark恢复阻塞
Condition 获取锁后调用await方法释放锁并在此等待 直到其他线程调用signal方法 等待队列
阻塞队列
ArrayBlockingQueue数组结构有界阻塞队列 一个锁
LinkedBlockingQueue 链表结构双向阻塞队列 添加移除两个锁
DelayQueue 支持优先级延时无界阻塞队列
PriorityBlockingQueue 基于优先级阻塞队列
SynchronousQueue 不存储元素阻塞队列
Fork/Join框架 大任务分割成小任务然后汇总结果
分割子任务分别放到双端队列里,启动几个线程分别从双端队列里获取任务执行。子任务执行完的结果都放在另外一个队列里,启动一个线程从队列里取数据,然后合并这些数据。
原子操作类
AtomicBoolean:原子更新布尔类型
AtomicInteger:原子更新整型
AtomicLong:原子更新Long类型
AtomicIntegerArray:原子更新整型数组里的元素
AtomicLongArray:原子更新长整型数组里的元素
AtomicReferenceArray:原子更新引用类型数组里的元素
AtomicReference:原子更新引用类型
AtomicReferenceFieldUpdater:原子更新引用类型里的字段
AtomicMarkableReference:原子更新带有标记位的引用类型
AtomicIntegerFieldUpdater:原子更新整型的字段的更新器
AtomicLongFieldUpdater:原子更新长整型字段的更新器
AtomicStampedReference:原子更新带有版本号的引用类型
并发工具类
CountDownLatch 等待多线程完成
CyclicBarrier 同步屏障 可循环使用,提供一些其他方法,比如阻塞线程数量 一组线程全部达到才继续运行
Semaphore 信号量 控制同时访问特定资源的线程数量
Exchanger 线程数据交换
synchronized锁普通方法(对象锁)和锁静态方法(类锁,class锁)
CAS compareAndSwapObject
包含三个参数CAS(V,E,N)V表示要更新的变量,E表示预期的值,N表示新值。只有当V的值等于E时,才会将V的值修改为N
解决ABA问题,添加版本号
volatile不能更新依赖当前值,只能保证可见性
(7)数据库
数据库事物acid 原子性,一致性,隔离性,持久性
Mysql存储引擎
MyISAM 非事物安全 支持全文索引
InnoDB 事物安全 支持行锁 支持外键
缓存
redis内存回收 挑选最近最少使用淘汰 将要过期淘汰 淘汰过期
redis支持丰富数据类型,支持string,list,set,sorted set,hash
redis支持事物,可以持久化数据,部分数据存在磁盘上
redis持久化方式 rdb只包含一个文件,定时备份 aof更高的安全性,每秒备份,文件大,恢复速率慢
Mybatis #{} 预编译,参数转义字符串,防止sql注入,编译好sql再取值 ${}取值后再编译SQL
半自动,sql容易优化 hibernate全自动,数据库无关,更好的二级缓存
(8)设计模式
23种设计模式,6大原则 开闭原则,里氏替换,依赖倒转,接口隔离,迪米特(最少知道),合成复用
(9)算法
优先队列PriorityQueue 实现了小根堆
是否有环 用两个速度不等的指针
(10)高可用,分布式
spring cloud + Eureka服务注册发现 + Ribbon客户端负载均衡 + Feign rest调用 + Hystrix容错处理 + Zuul网关
+ spring cloud config 统一配置管理 + spring cloud Sleuth微服务追踪
Eureka与微服务保持心跳 短时间丢失大量心跳进入自我保护模式
Ribbon负载均衡算法轮询,随机数,实现自定义的
Hystrix 设置请求超时,断路器 fallback属性返回默认值
分布式锁
基于数据库(建表方法名唯一索引 插入取得锁)
基于缓存(Redis等 uuid判断是否是该线程加锁)
基于Zookeeper(该方法对应目录创建节点,最小节点获得锁)
一个分布式系统不可能同时满足C(一致性)、A(可用性)和P(分区容错性)
Zookeeper保证CP
Eureka保证AP
(11)网络
三次握手 建立连接
1客户端发送到服务器SYN_SENT
2服务端发送给客户端确认SYN_RECV
3客户端发送确认到服务器ESTABLISHED连接成功
四次握手 断开连接
1客户端发送请求断开连接
2服务端返回收到
3服务端关闭连接发送给客户端信息
4客户端发送确认
TCP与UDP区别总结:
1、TCP面向连接,要先建立连接;UDP是无连接的,即发送数据之前不需要建立连接
2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
3、UDP具有较好的实时性,工作效率比TCP高
4.每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
5、TCP对系统资源要求较多,UDP对系统资源要求较少。
同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO。
BIO同步阻塞 一个连接一个线程
NIO同步非阻塞 一个请求一个线程 适用于链接数目多较短
AIO异步非阻塞 一个有效请求一个线程 适用于链接数目多较长
netty和mina的区别 netty更晚 netty版本发布快 netty暴露udp的特性,mina把udp当作面向连接
(12)消息队列
Kafka海量数据,不支持事物处理
ActiveMQ支持事物
RabbitMq可靠性高于kafka 性能好于activemq
kafka流量消峰 拉模型
aop在spring原生中什么的地方用过
静态代理什么地方用过
dubbo rpc协议 rpc不是协议 rpc介绍
http协议的
http和tcp协议的区别
http协议请求网页的过程
http学习
mq模式 推和拉的区别
数组和链表的区别
LinkedList时间复杂度
gc回收器区别
ThreadLocal
静态代理的例子
Spring如何解决对象的循环依赖引用?( 只支持Singleton作用域的, setter方式的循环依赖!不支持构造器方式和prototype的循环依赖)
树