一、ConcurrentHashMap 介绍一下
组成单位是Segment桶,一个桶中包含有Entry数组,类似于HashMap,一个ConcurrnetHashMap就是一个Segments数组,包含2^n个桶。
1、在同一Segment桶中两个线程进行写操作,其中一个会阻塞等待另一个进程完成操作。
2、在同一Segment桶中两个线程进行一写一读操作,是可以并发执行的。
3、在不同Segment桶中两个线程进行写操作,是可以并发执行的。
每个Segment桶都有一把锁,会让并发操作效率提高。
几个方法:
get():
对key进行hash操作,通过hashcode定位到在哪个Segment桶对象,再次通过hash值在桶中定位到准确位置。
put():
1、对key进行hash操作,通过hashcode定位到在哪个Segment桶对象。
2、获取可重入锁。
3、再次通过hash值在桶中定位到具体位置。
4、插入或者覆盖Entry键值对。
5、释放锁。
ConcurrentHashMap统计size解决一致性的问题?
size方法大概是
1、遍历所有的Segment。
2、把Segment数量都加起来
3、把Segment修改次数加起来
4、判断这次的修改次数和上一次的区别,大于则说明有修改,重新统计并记录查询次数。没改变就返回统计结果。
5、查询次数超过阈值,对另一个Segment加锁,重新统计。
6、再次判断,由于已经加锁不会put进元素,所以肯定成功。
7、释放锁。
有点像乐观锁悲观锁,先假设查询的时候不会有元素的增加,当尝试次数大于阈值时转换为悲观锁,为每个Segment加锁保证查询成功。
二、JMM内存模型
是一种抽象的规范,用来屏蔽不同硬件和操作系统的差异,让java更好地实现跨平台
大概样子
1、主内存
相当于计算机中的内存,主内存被所有的线程共享,对于一个共享变量(比如静态变量,堆中实例等),主内存存储了真正的数据
2、工作内存
相当于计算机中的高速缓存,每一个线程都拥有自己的工作内存,对一个共享变量来说,工作内存当中存储了它的 副本,使用工作内存的原因
是因为直接操作主内存速度慢
关于volatile见上一篇
三、B-树介绍一下
其实就是B树,一个m阶的B树具有以下特征:
1、根节点至少有两个孩子
2、每个中间节点都包含k-1个元素和k个孩子。其中m/2<=k<=m
3、每一个叶子节点都包含k-1个元素,其中m/2<=k<=m
4、所有的叶子节点都位于同一层。
5、每个节点中元素从小到大排列,节点当中k-1个元素正好是k个孩子包含的元素的值域分划
为什么要用B树
查询速度快是因为高度短。如果是二叉平衡树可能会找的很深,进行多次IO读取会很耗时间,B树比较次数可能大于二叉平衡树,可这样耗时远远小于IO读取。
在增加或删除元素时可以维护自平衡,主要应用于文件系统、部分非数据库索引(MongoDB)
四、B+树介绍一下
一个m阶的B+树具有以下特征:
1、有k个子树的中间节点包含有k个元素(B树是k-1个元素)每个元素不保存数据,只用来当索引,所有的数据都保存在叶子节点。
2、所有的叶子节点中包含了全部元素的信息,每一个叶子节点都带有指向下一个节点的指针,形成了一个有序链表。
3、每一个父节点的元素都出现在子元素中,是子节点最大(或最小)元素。
和B树的区别
1、在B树中,无论中间节点和叶子节点都带有卫星数据(即索引元素指向的数据记录,比如索引指向数据库中某一行,而在B+树中,只有叶子节点带有卫星数据,其余中间节点仅仅是索引,没有数据关联。
2、由于B+树中间节点没有卫星数据,同样大小的磁盘页可以存放更多数据。如果B+和B树数据量相同,B+更加矮胖,查询IO操作更少
3、B+树查询必须查找到最后的叶子节点,而B树找到匹配元素即可,无论在哪。
4、B树的查找性能不稳定,根据查找内容会变化,B+则是很稳定。
5、进行范围查询时,B树要查询到两个节点之间的元素,要做很多遍历操作,而B+树直到找到边界元素根据链表遍历即可。
五、TCP 三次握手四次挥手
三次握手:
发送方发送SYN数据包
接受方发送SYN/ACK数据包
发送方发送ACK数据包
四次挥手:
A-B打电话
A说话,说完了
B知道了
B说话,说完了
A知道了
六、IP地址和MAC地址区别
IP地址:互联网协议地址,用于屏蔽不同计算机的物理硬件的差异
MAC地址:计算机网卡硬件地址,用来定义网络设备的位置