抛砖引玉先拿一道面试题祭天
HashMap底层是数组+链表结构,数组被分为一个个桶bucket,在不产生冲突时更多使用数组,添加来讲是加入尾部,时间复杂度为0(1),查询的时间的复杂度都要遍历一遍,所以时间复杂度为0(n)在jdk1.8之后对HashMap做了变化,加入红黑树,在链表大于阈值(TREEIFY_THRESHOLD, 8)的时候会进行由链表到红黑树的转化(查找的时间复杂度为O(logn))
在jdk1.7版本中,ConcurrentHashMap的数据结构是segment数组和多个HashEntry组成,就是将链表分成很多的table进行分段加锁,使用了锁分段技术,每个都相当于是HashMap的数据存储,此外segment继承了ReentrantLock可重入锁
put操作通过key的hash定位segment的位置,如果没初始化,就通过cas操作进行赋值,然后进行第二次hash,找到相应的位置,在插入数据时,会通过尝试ReentrantLock的tryLock方法进行获取锁,如果获取到就放入尾端,没有的话当前的线程就以自旋方式去继续调用tryLock()方法去获取锁,超过指定次数就挂起,等待唤醒,保证了不可冲突性,完成了线程安全的意义
get的话也一样,先通过key的hash找到segment的位置,然后再次hash找到指定的hashEntry,在jdk1.8版本中,直接使用的是node+链表+红黑树的数据结构来实现,并发控制使用synchronized和CAS来操作
对于早期的版本,put操作通过二次哈希避免了哈希冲突,然后以Unsafe的调用方式,直接获取相应的segment,然后进行线程安全的put操作,后期版本中不再使用segment,初始化操作大大简化,修改为lazy-load,有效避免了初始化开销,数据存储利用了volatile来保证了可见性,没有hash冲突就直接cas插入实现了无锁操作,使用 Unsafe、LongAdder 之类底层手段,进行极端情况的优化。
总结
开放定址法 :关键字key的哈希地址p=H(key)再次冲突的时候,以p为基础,产生另一个哈希地址p1,如果p1仍然冲突,在以p为基础,产生第二个哈希地址p2,直到找出一个冲突的哈希地址pi,将相应的元素存入其中
再哈希法 :同时构造多个不同的哈希函数,Hi=RH1(key) i=1,2,3,4….k,当哈希地址Hi=RH1(key)发生冲突时,再计算Hi=RH2(key)….. 直到冲突不再发生,但是增加了计算的时间
链地址法 : 将所有的哈希地址为i的元素构成一个同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找,插入和删除主要在同义词链中进行
第一:物理层,机械电子等在通信信道上的原始比特流,利用传输介质,比如网卡,实现比特流的透明传输
第二:链路层,物理寻址,将比特流转为逻辑传输线路,变为帧,交换机等介质
第三:网络层,通过路由算法,为报文或者分组通过控制子网的运行,逻辑编址,分组,切分传输,路由,选择最适当的路径
第四:传输层,数据分割,排序进行重组,保证报文的正确传输,tcp
第五:会话层,不同机器上的用户建立管理会话
第六:表示层,协议,加密,转换,压缩解压缩
第七:应用层,更方便的应用TCP的http协议,头文件解析分离
面向连接,可靠地,基于字节流的传输层通信协议,将应用层的数据流分割成报文段,并发送给目标节点的TCP数据包都有序号,对方收到则发送ACK确认,未收到则重新发送,给包编码,顺序重组,检验和校验数据在传输过程中是否失真
TCP flags的8个标志位重要的点:
ACK,为1,确认序号有效,为0则报文中不含确认信息
SYN,同步序号,用于建立连接过程,在连接过程中发送端ACK和SYN捎带1,就表明发送了确认请求信息
基于全双工的通信,直到被一方或者双方关闭为止
第一次握手:建立连接,客户端发送syn包到服务器,并进入syn-send状态,等待服务器确认
第二次握手:服务器收到syn包,必须确认客户的syn的,同时自己发送一个syn,即是syn+ack,此时服务器进入syn-recv状态
第三次握手:客户端收到服务器的syn+ack包,向服务器发送确认包ack,此包发送完毕之后,客户端和服务器进入到establishen 状态
syn超时,server收到client的syn,回复syn+ack未收到ack确认,会处于中间状态,那么server就不断的重新发送,直至超时,linux一般默认超过63秒之后会断开这个连接状态,针对这个syn flood攻击的防护措施:syn会被一直攻击,让服务端处于等待状态,直至耗尽syn队列,那么会通过tcp-syncookies参数发送回syn cookie,若为正常的连接则client会发回这个syn cookie,直接建立连接,不需要进行三次握手
保活机制:tcp的内部机制,向对方发送探测报文,未收到响应就继续发送保活报文,尝试次数达到保活探测次数的最大值就确认中断连接,这段时间为保活时间
第一次挥手:客户端发送断开连接:client发送一个fin,用来关闭client到server的数据传送,client进入到fin-wait-1状态 (不会发送数据)
第二次挥手:server收到fin后,发送一个ack给client,确认序号为收到序号+1,server进入close-wait状态 (补充的数据传入给客户端)
第三次挥手:server发送一个fin,用来关闭server到client的数据传输,server进入到last-ack状态
第四次挥手:client收到fin之后,client进入到time-wait状态,接着发送一个ack给server,确认序号为收到的序号+1,server进入closed状态,完成四次握手(2Xmsl)
面向连接 -- 面向无连接
可靠性 -- 握手确认重传机制
有序性 -- 序列性,序列号确认到达的重排是有序号的
速度 -- udp快,tcp要创建连接,保证可靠性,有序性等额外的开销,所以udp更快
重量 -- tcp是20个字节,udp是8个字节
基于RTO的,RTO重传的时间间隔,在传输完成一次连接时,开启定时器,在分析RTT之后,RTT发送一个数据包到收到对应的ack,由所花费的时间,根据算法设定一个时间间隔,超过这个时间就会重新传送
保证流量控制和乱序重排,保证TCP的可靠性和流控特性,滑动窗口的配置可以根据设置和应用上的设备进行限制,重传机制是滑动窗口的实现的基本条件也是用来作为流量控制的基础
滑动窗口:发送方通过统计最大就是在发送端已发送未确认ack和未发送但允许ack确认的统称为发送区,接受方未接收准备发送接收回执确认为接收端,发送方收到ack的连续确认,段的发送内容就会进行发送连续,就会移动,当接收端收到连续的请求之后,同时也会对发送端进行流量限制
在浏览器地址栏输入url,按下回车之后它经历了森么?
get请求和post请求的区别?
https和http的区别?
中间层 SSL 安全套接层,更名为TLS:为网络通信提供安全及数据的一种安全协议
采用的是身份验证和数据加密保证网络通信的安全和数据的完整性
但是HTTPS在常规的使用中,通常是通过HTTP浏览器默认的跳转,301、302进行的,会有被劫持的风险,出于这个可以用过HSTS优化