Java基础
1.NIO的实现原理
NIO主要有三大核心部分:Channel(通道),Buffer(缓冲区), Selector。传统 IO 基于字节流和字符流进行操作,而 NIO 基于 Channel 和 Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。Selector(选择区)用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个线程可以监听多个数据通道。
IO是面向流的,而NIO是面向缓冲区的。
NIO的缓冲区:
JavaIO面向流意味着每次从流中读取一个或多个字节直到读取完所有字节,数据没有被缓存到任何地方,不能前后移动流中的数据,只有将其混村到一个缓冲区中。而NIO可以,数据读取到缓冲区中随后可以在缓冲区中移动,但是,还需要检查是否该缓冲区中包含所有您需要处理的数据。而且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据。
NIO的非阻塞:
JavaIO各种流是阻塞的,一个线程调用读写方法时,线程会被阻塞直到数据被处理,期间不能干别的事。
NIO的非阻塞,当一个线程从某通道发送读取数据请求,它只能得到当前可用的数据,如果没有他所需要的数据,不会等待也不会阻塞,直到数据变得可用之前它都可以去干任何事。 线程通常将非阻塞 IO 的空闲时间用于在其它通道上执行 IO 操作,所以一个单独的线程现在可以管理多个输入和输出通道(channel)。
2.HashMap、HashSet
HashMap实现原理
HashMap允许K-V为空,当其key为null时,调用putForNullKey方法,放入到table[0]的这个位置
HashMap的扩容机制:
扩容必须满足两个条件:
1、 存放新值的时候当前已有元素的个数必须大于等于阈值 (数组大小*loadfactor加载因子大小)
2、 存放新值的时候当前存放数据发生hash碰撞(当前key计算的hash值换算出来的数组下标位置已经存在值)
扩容后放在二倍大小的新数组中
void resize(int newCapacity) {
Entry[] oldTable = table;
int oldCapacity = oldTable.length;
//判断是否有超出扩容的最大值,如果达到最大值则不进行扩容操作
if (oldCapacity == MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return;
}
Entry[] newTable = new Entry[newCapacity];
// transfer()方法把原数组中的值放到新数组中
transfer(newTable, initHashSeedAsNeeded(newCapacity));
//设置hashmap扩容后为新的数组引用
table = newTable;
//设置hashmap扩容新的阈值
threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
}
transfer()在实际扩容时候把原来数组中的元素放入新的数组中
void transfer(Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;
for (Entry<K,V> e : table) {
while(null != e) {
Entry<K,V> next = e.next;
if (rehash) {
e.hash = null == e.key ? 0 : hash(e.key);
}
//通过key值的hash值和新数组的大小算出在当前数组中的存放位置
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
}
}
}
因为上面这两个条件,所以存在下面这些情况
(1)、就是hashmap在存值的时候(默认大小为16,负载因子0.75,阈值12),可能达到最后存满16个值的时候,再存入第17个值才会发生扩容现象,因为前16个值,每个值在底层数组中分别占据一个位置,并没有发生hash碰撞。
(2)、当然也有可能存储更多值(超多16个值,最多可以存26个值)都还没有扩容。原理:前11个值全部hash碰撞,存到数组的同一个位置(这时元素个数小于阈值12,不会扩容),后面所有存入的15个值全部分散到数组剩下的15个位置(这时元素个数大于等于阈值,但是每次存入的元素并没有发生hash碰撞,所以不会扩容),前面11+15=26,所以在存入第27个值的时候才同时满足上面两个条件,这时候才会发生扩容现象。
HashSet实现原理
HashSet的去重原理:
HashMap 的 put() 方法添加 key-value 对时,当新放入 HashMap 的 Entry 中 key 与集合中原有 Entry 的 key 相同(hashCode()返回值相等,通过 equals 比较也返回 true),新添加的 Entry 的 value 会将覆盖原来 Entry 的 value(HashSet 中的 value 都是PRESENT),但 key 不会有任何改变,因此如果向 HashSet 中添加一个已经存在的元素时,新添加的集合元素将不会被放入 HashMap中,原来的元素也不会有任何改变,这也就满足了 Set 中元素不重复的特性。
3.LinkedHashMap
LinkedHashMap实现原理
4.ConcurrentHashMap
ConcurrentHashMap实现原理
成员是segment数组,而segment数组的数据结构为HashEntry的数组,HashEntry存储键值对可以构成链表。
并发写:put方法要加锁完成,先调用ConcurrentHashMap的put()方法,再调用segment的put()方法,先加锁得到hash对应table中的索引index,再找到hash对应的具体是那个桶,即哪个hashEntry链表,操作完后解锁。
加锁操作针对的hash值对应的是某个segment而不是整个ConcurrentHashMap,因此其他线程也可以对别的segment进行put操作,同时读线程不会因本线程加锁而阻塞。
5. hashcode与equals方法
equals只能用于对象间来判断是否相等,hashcode计算对象的哈希码
- equals相等的两个对象,hashcode一定要相等,但hashcode相等的两个对象不一定equals相等
- 重写对象的equals方法必须重写hashCode方法,尽管不写也能通过编译;
6. RuntimeException和Exception Error
Throwable 是 Java 语言中所有错误或异常的超类。下一层分为 Error 和 Exception。
Error:程序发生不可控的错误时通常通知用户并终止程序的进行,它代表编译时间和系统错误,用来指示合理的应用程序不应该试图捕获严重问题,由java虚拟机生成并抛出,包括动态连接失败,虚拟机错误等。
Exception:分为CheckedException和RuntimeException
RuntimeException: 如 NullPointerException 、 ClassCastException是那些可能在 Java 虚拟机正常运行期间抛出的异常的超类
CheckedException:一般是外部错误,这种异常都发生在编译阶段,Java 编译器会强制程序去捕获此类异常,即会出现要求你把这段可能出现异常的程序进行 try catch,该类异常一般包括几个方面:
- 试图在文件尾部读取数据
- 试图打开一个错误格式的 URL
- 试图根据给定的字符串查找 class 对象,而这个字符串表示的类并不存在
如 I/O 错误导致的 IOException、SQLException。
7.注解的使用
Java注解
8. 基本数据类型
数值型:
整数类型:
类型 | 大小 | 范围 |
---|---|---|
byte | 1字节 | -128~127 |
short | 2字节 | -2^15 ~ 2^15 -1(-32768~32767) |
int | 4字节 | -2^31 ~2^31-1 |
long | 8字节 | -2^63 ~2^63-1 |
浮点类型:
类型 | 大小 | 范围 |
---|---|---|
float | 4字节 | -2^31- 2^31-1 |
double | 8字节 | -2^63 -2^63-1 |
字符型:
char | 2字节 | 0-2^16-1 |
---|
布尔型:
boolean | 1字节 | true/false |
---|
9. 五种常见的网络IO模型
1.阻塞IO模型
2.非阻塞IO模型
3.多路复用IO模型
4.信号驱动IO模型
5.异步IO模型
多线程并发编程
1.线程池的构造参数及其含义,如何确定线程池中的线程个数?
https://blog.csdn.net/ye17186/article/details/89467919
2.定时线程池如何实现?
3.synchronized、volatile关键字
4.原子性、可见性、有序性
5.JVM内存模型
6.可重入锁ReentrantLock
7.ThreadLocal实现原理
8.AQS底层实现,与ReentrantLock的关系
JVM知识点
1.内存区域划分
2.OOM分区域介绍
3.对象分配与回收
4.CMS与G1垃圾回收器
5.对象可达性分析
6.类加载机制
7.JVM调优参数
8.Full GC、Minor GC
MySQL知识点
1.MySQL隔离级别
mysql事务隔离级别:4个,级别从低到高: read uncommitted < read committed < repeatable read < serializable
1. read uncommitted 读未提交
可以读取到别的事务中未提交的数据,实际上数据并未提交到数据库,造成脏读,不可重复读,幻读。
2. read committed 已提交读
只能读取到其他事务提交的数据,两次读取的结果不一致,造成不可重复读,幻读。
3. repeatable read 可重复读
其他事务的提交无影响,每次读取的结果都一样,造成幻读。
4.serializable 可序列化
当前会话操作时,其他会话的写操作将被挂起,对性能造成影响,通常会使用其他隔离级别加上并发锁机制。
2.一致性视图
3.日志模块:undo log,redo log和bing log
4.索引结构,回表,最左前缀原则
5.间隙锁,幻读,MVCC是否可以解决幻读
6.SQL优化
网络协议
1.TCP与UDP区别
2.TCP可靠性如何保证
3.TCP网络包分片与重组
4.三次握手与四次挥手,状态转换
5.SSL握手协议使用的加密算法,非对称加密的缺点
6.XSS与CSRF介绍
Spring&MyBatis
1.Spring IOC与AOP原理
2.Spring源码解读,启动方式,配置顺序
3.SpringMVC和Spring父子容器的关系
4.Spring的事务实现方式
5.如何自定义实现SpringBoot中的starter
6.Mybatis中#与$符号的区别?