Java基础
- 创建线程的方式有哪些?
- 继承Thread类创建线程类
- 通过Runnable接口创建线程类
- 通过Callable和Future创建线程
- Callable和Runnable有什么区别?
- Runnable 接口 run 方法无返回值;Callable 接口 call 方法有返回值,支持泛型
- Runnable 接口 run 方法只能抛出运行时异常,且无法捕获处理;Callable 接口 call 方法允许抛出异常,可以获取异常信息
- 简要描述线程池的基本原理,并介绍常见的阻塞队列
将多个任务无序或有序的放入队列,多个线程执行队列任务;
ThreadPoolExecutor线程池类参数详解
- corePoolSize 核心线程数量,线程池维护线程的最少数量
- maximumPoolSize 线程池维护线程的最大数量
- keepAliveTime 线程池除核心线程外的其他线程的最长空闲时间,超过该时间的空闲线程会被销毁 unit keepAliveTime的单位,TimeUnit中的几个静态属性:NANOSECONDSMICROSECONDS、MILLISECONDS、SECONDS
- workQueue 线程池所使用的任务缓冲队列
- threadFactory 线程工厂,用于创建线程,一般用默认的即可 handler 线程池对拒绝任务的处理策略
常见的阻塞队列
- ArrayBlockingQueue
- LinkedBlockingQueue
- SynchronousQueue
- PriorityBlockingQueue
- DelayQueue
- 简要描述线程池实现原理
所谓线程池本质是一个hashSet。多余的任务会放在阻塞队列中。
只有当阻塞队列满了后,才会触发非核心线程的创建。所以非核心线程只是临时过来打杂的。直到空闲了,然后自己关闭了。
线程池提供了两个钩子(beforeExecute,afterExecute)给我们,我们继承线程池,在执行任务前后做一些事情。
线程池原理关键技术:锁(lock,cas)、阻塞队列、hashSet(资源池)
- volatile关键字有什么用处?
volatile 关键字是 Java 虚拟机提供的最轻量级的同步机制,使用volatile可能比锁更快,但在某些情况下它不起作用。在 Java 5 中扩展了 volatile 有效的情况范围。 特别是,双重检查加锁机制现在可以正常工作。
- Java内存中的哪些区域会发生OOM?
除了程序计数器都有可能
- 常见垃圾回收算法有哪些?
- 标记清除算法
- 复制算法
- 标记压缩算法
- 分代收集算法
- 引用计数算法
- 根搜索算法
- 哪些对象可以作为GC Root?
- java虚拟机栈中的引用的对象。
- 方法区中的类静态属性引用的对象。 (一般指被static修饰的对象,加载类的时候就加载到内存中。)
- 方法区中的常量引用的对象。
- 本地方法栈中的JNI(native方法)引用的对象
- 常见垃圾回收器有哪些?
1 .Seial New: 单线程收集器,收集垃圾时,会停止其他任务执行,采用复制算法;
Parallel New:多线程收集器,复制算法
Servial Old:单线程收集器,标记整理算法;
Paraller Old:多线程收集器,标记整理算法;5. Parallel Scavenge:多线程收集器,复制算法;
CMS 收集器:是一种以获得最短回收停顿时间为目标的收集器,标记清除算法。运作过程:初始标记、并发标记、重新标记、并发清除,收集结束后会产生大量内存碎片;
G1收集器:标记整理算法实现,运作流程:初始标记、并发标记、最终标记、筛选标记,不会产生内存碎片
ZGC:JDK11出的,在小堆空间下,停顿时间会比G1短;没有新生代、老年代概念,只有内存区域Page的概念;进行完GC后,会对Page空间进行压缩,避免碎片化;CMS&G1只在对象头标记,ZGC会在对象的指针上标记。
Shenandoah:
注意:目前大多数用的 G1 收集器;如何避免ThreadLocal产生内存泄漏?
ThreadLocal 是基于 ThreadLocalMap 实现的,这个 Map 的 Entry 继承了 WeakReference ,而 Entry 对象中的 key 使用了 WeakReference 封装,也就是说 Entry 中的 key 是一个弱引用类型,而弱引用类型只能存活在下次GC之前。
如果线程调用 ThreadLocal 的 set 设置变量,当前 ThreadLocalMap 则会新增一条记录,但由于发生了一次垃圾回收,此时的key 值就会被回收,而 value 值依然存在在内存中,由于当前线程一直存在,所以 value 值将一直被引用。
这些被垃圾回收掉的 key 就会一直存在一条引用链的关系:Thread --> ThreadLocalMap --> Entry --> Value。这条引用链会导致 Entry 不会被回收,Value 也不会被回收,但 Entry 中的 key 却已经被回收的情况发生,从而造成内存泄漏。
我们只需要在使用完该 key 值之后,将 value 值通过 remove 方法 remove 掉,就可以防止内存存泄露了。
Java 集合
简要描述HashMap存入K:V的过程
LinkedHashMap是如何实现有序性的?
LinkedHashMap底层是数组加单向链表加双向链表,核心使用双向链表实现有序性
- 简要描述ArrayList扩容机制与过程
如果调用空构造方法,默认elementData为10;
扩容倍数为1.5倍 oldCapacity +oldCapacity >>1 //oldCapacity =10
可以指定大小,如果指定大小以后,oldCapacity 为设置的大小
常用框架
- 简要描述Spring Bean生命周期
Spring启动,查找并加载需要被Spring管理的bean,进行Bean的实例化
Bean实例化后对将Bean的引入和值注入到Bean的属性中
如果Bean实现了BeanNameAware接口的话,Spring将Bean的Id传递给setBeanName()方法
如果Bean实现了BeanFactoryAware接口的话,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入
如果Bean实现了ApplicationContextAware接口的话,Spring将调用Bean的setApplicationContext()方法,将bean所在应用上下文引用传入进来。
如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessBeforeInitialization()方法。
如果Bean 实现了InitializingBean接口,Spring将调用他们的afterPropertiesSet()方法。类似的,如果bean使用init-method声明了初始化方法,该方法也会被调用
如果Bean 实现了BeanPostProcessor接口,Spring就将调用他们的postProcessAfterInitialization()方法。
此时,Bean已经准备就绪,可以被应用程序使用了。他们将一直驻留在应用上下文中,直到应用上下文被销毁。
如果bean实现了DisposableBean接口,Spring将调用它的destory()接口方法,同样,如果bean使用了destory-method 声明销毁方法,该方法也会被调用。
- Spring中用到了哪些设计模式?
- 工厂模式:工厂模式可以通过 BeanFactory 或 ApplicationContext 创建 bean 对象
- 单例模式:在我们的系统中,有一些对象其实我们只需要一个,比如说:线程池、缓存、对话框、注册表、日志对象、充当打印机、显卡等设备驱动程序的对象。
- 观察者模式:ApplicationContextEvent
- 代理模式:AOP
- ……
- 简要描述AOP实现原理
Spring提供了两种方式来生成代理对象: JdkProxy和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。默认的策略是如果目标类是接口,则使用JDK动态代理技术,否则使用Cglib来生成代理。
MySQL数据库
简要描述SQL语句执行过程
客户端把语句发给服务器端执行
语句解析
语句合法性检查
语言含义检查
确定最佳执行计划
语句执行
返回数据
简要描述WAL机制及其实现原理
WAL,全称是Write-Ahead Logging, 预写日志系统。指的是 MySQL 的写操作并不是立刻更新到磁盘上,而是先记录在日志上,然后在合适的时间再更新到磁盘上。这样的好处是错开高峰期。日志主要分为 undo log、redo log、binlog。这三种在之前的博客已经详细说过了,作用分别是 " 完成MVCC从而实现 MySQL 的隔离级别 "、" 降低随机写的性能消耗(转成顺序写),同时防止写操作因为宕机而丢失 "、" 写操作的备份,保证主从一致 "。关于这三种日志的内容讲的比较分散且具体的执行过程没有提到,所以这里来总结一下这三种日志。
简要描述MySQL事务实现原理
如果一条查询SQL优化到了极限,还有哪些方法可以提升查询速度?
索引
修改 my.cnf 配置 提升配置
提升宿主机物理配置
Redis
- 简要介绍Redis的5种基础数据类型及其对应数据结构
Redis为什么快?
Redis 的大部分操作在内存上完成,再加上它采用了高效的数据结构,例如哈希表和跳表,这是它实现高性能的一个重要原因。
就是 Redis 采用了多路复用机制,使其在网络 IO 操作中能并发处理大量的客户端请求,实现高吞吐率。
数据结构,具体见上
Redis在什么情况下会删除Key?是怎么删除的?
- 被动删除:当读/写一个已经过期的key时,会触发惰性删除策略,直接删除掉这个过期key
- 主动删除:由于惰性删除策略无法保证冷数据被及时删掉,所以Redis会定期主动淘汰一批已过期的key
- 当前已用内存超过maxmemory限定时,触发主动清理策略
RabbitMQ
- RabbitMQ是如何做到消息不丢失的
1.消息持久化
2.ACK确认机制
3.设置集群镜像模式
4.消息补偿机制
- 简要描述RabbitMQ延迟队列实现原理
1、生产者发送消息的队列中,且针对该队列没有消费者
2、由于队列没有消费者,消息在过期之后会进入到死信队列中
3、监听死信队列,并对死信队列中的消息进行消费