1.索引的添加:二叉树、红黑树(自动更新的二叉树平衡树)、Hash、B-Tree 【磁盘IO、内存】
2.存储引擎:
3.联合索引
4.栈、堆
5.垃圾回收机制(通过jdk自带visualvm可查询某类的具体执行过程)
cmd->jvisualvm
6.jmm内存模型(Java线程内存模型):和cpu缓存模型类似
MESI缓存一致性协议
7.volatile
A. 无论synchronized关键字加在方法上还是对象上,如果它作用的对象是非静态的,则它取得的锁是对象;如果synchronized作用的对象是一个静态方法或一个类,则它取得的锁是对类,该类所有的对象同一把锁。
B. 每个对象只有一个锁(lock)与之相关联,谁拿到这个锁谁就可以运行它所控制的那段代码。
C. 实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。
8.spi动态服务扩展机制
提供一个类去读取指定目录下的文件,读取文件的内容 通过反射创建对象。
9.IoC、AOP
IoC(Inversion of Control,控制倒转)
DI(Dependency Injection,依赖注入):Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的
10.spring自动装配
11.高并发
AQS同步器(抽象队列同步器)
cas比较与交换-原子算法
12.hashmap
数组+链表+红黑树
要知道hashmap是什么,首先要搞清楚它的数据结构,在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,hashmap也不例外。Hashmap实际上是一个数组和链表的结合体(在数据结构中,一般称之为“链表散列“)
当hashmap中的元素越来越多的时候,碰撞的几率也就越来越高(因为数组的长度是固定的),所以为了提高查询的效率,就要对hashmap的数组进行扩容,数组扩容这个操作也会出现在ArrayList中,所以这是一个通用的操作,很多人对它的性能表示过怀疑,不过想想我们的“均摊”原理,就释然了,而在hashmap数组扩容之后,最消耗性能的点就出现了:原数组中的数据必须重新计算其在新数组中的位置,并放进去,这就是resize。
那么hashmap什么时候进行扩容呢?当hashmap中的元素个数超过数组大小loadFactor时,就会进行数组扩容,loadFactor的默认值为0.75,也就是说,默认情况下,数组大小为16,那么当hashmap中元素个数**超过160.75=12的时候,就把数组的大小扩展为2*16=32,即扩大一倍**,然后重新计算每个元素在数组中的位置,而这是一个非常消耗性能的操作,所以如果我们已经预知hashmap中元素的个数,那么预设元素的个数能够有效的提高hashmap的性能。
hashmap8优化,不会出现死锁:
13.JAVA线程:
线程池执行策略:
14.单例模式
实现方式:
懒汉式:
是否 Lazy 初始化:是
是否多线程安全:否
实现难度:易
线程安全的:
是否 Lazy 初始化:是
是否多线程安全:是
实现难度:易
优点:第一次调用才初始化,避免内存浪费。
缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。
饿汉式:
是否 Lazy 初始化:否
是否多线程安全:是
实现难度:易
描述:这种方式比较常用,但容易产生垃圾对象。
优点:没有加锁,执行效率会提高。
缺点:类加载时就初始化,浪费内存。
静态内部类:
是否 Lazy 初始化:是
是否多线程安全:是
实现难度:一般
描述:这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。
反射攻击、
枚举模式:
JDK 版本:JDK1.5 起
是否 Lazy 初始化:否
是否多线程安全:是
实现难度:易
序列化、
jdk源码
15.Docker
16.mysql读写分离
atlas代理实现读写分离
17.微服务架构
18.高并发场景
基于redisson实现的分布式锁
搭建redisson 扔进spring管理