map的底层结构
jdk8中map底层结构是 数组+链表+红黑树组成的。
在map初始化会赋予一个固定长度的数组,放入数据的时候,先对key进行hash操作,计算对应的数组下标,并放入对应数组元素的链表头中,当再次放入key的hash值一样时,会将数据放在对应链表的头部,最先放入的元素在后面.当放入的链表长度大于8时,会用一个红黑树结构的treemap来替换掉原来的链表结构,它的查找时间是O(logn).
map有哪些实现 以及ConcurrentHashMap的线程安全是怎么实现的.
HashMap, LinkedHashMap, ConcurrentHashMap.
ConcurrentHashMap的线程安全主要是 Synchorized + CAS + volatile 实现的。get方法由于变量是用了Volatile修饰,所以不加锁也能读取到最新的值。put方法加上了Synchorized锁。
拓展延伸:红黑树
Object的方法
getClass 方法,hashCode方法,toString方法,wait方法,notify方法,clone方法,finalize方法.
讲讲NIO
NIO是非阻塞的同步I/O,非阻塞体现在连接是非阻塞的,同步体现在进行I/O操作时是同步等待的。
NIO主要有三个主要的概念,Channel,缓冲区Buffer和Selector。Channel是一个通道的意思,负责连接,缓冲区Buffer是一个容器对象,发送给一个Channel的所有对象必须先放入缓冲区Buffer中,同理,从Channel中读取的所有对象也必须从Buffer中读取。Selector就是一个你对发生在Channel上感兴趣的事件做出响应的一个对象,由它告诉你发生了什么事情。
注: 深入问问题就是buffer中数据的读写,为什么要调用flip方法(单索引),
OSI 7层网络模型
物理层: 利用传输介质为数据链路层提供物理连接,实现比特流的透明传输
数据链路层: 将物理层的位流形式的数据封装成帧,传输到上一层. 有MAC/LLC协议..
网络层: 将数据链路层的数据转换成数据包然后通过路径选择,分段组合,顺序,进/出路由控制将数据从一个网络设备传输到另一个传输设备.
传输层: 该层起承上启下的作用,将上层协议段数据变成报文的来进行正确传输. 有TCP/IP, UDP协议等等
会话层: 维持用户程序和网络之间的会话通信,使用远程地址建立连接(域名)
表示层: 通信数据的加密解密,数据格式的处理
应用层: 用户与应用程序的交互层.
第1-3层为通信层,5-7层为资源层,4层为承上启下层。
用户输入 baidu.com 到 baidu.com 返回数据,期间发生了什么
客户端通过域名访问DNS服务器得到具体的ip地址,通过这个ip地址发送HTTP会话,建立HTTP长连接, 通过TCP协议对数据进行封装,传输到网络层,网络层找到对应的baidu服务器,服务器再通过负载均衡找到对应的响应服务器.响应服务器再组织数据通过网络层返回数据给用户所在主机,用户的浏览器就会解析返回的数据并渲染显示在用户面前。
注: 要详细讲的话,很长很长。主要是协议,负载均衡等知识。
TCP 协议为什么是可靠的
确认机制: 三次握手同步双方的“序列号+确认号+窗口大小信息”
重传机制: CheckSum校验失败,丢包或者延时,发送端重传
数据排序: TCP有专门的序列号SN字段,可提供数据的re-Order
流量控制: 窗口和计数器的使用,TCP窗口中会指明双方能够发送接收的最大数据量
拥塞控制:
- “慢启动”(Slow Start)
- “拥塞避免”(Congestion avoidance)
- “快速重传 ”(Fast Retransmit)
- “快速恢复”(Fast Recovery)
为什么wait和notify方法只能在 Synchorized 块中使用
抛开再java中不加Synchorized块出现的异常问题,还有可能会导致竞态条件的问题。当另一个线程先调用notify,再调用wait的话,有可能会永远的wait下去。
SpringBoot启动流程
先将应用打包成一个jar/war包,再用JarLancher根据jar/war的文件所在url创建一个Archive,然后构建一个LaunchedURLClassLoader类加载器,再去加载我们的应用主类,从而启动引用程序。
Spring如何处理一个请求
DispatcherServlet –> HandlerMapping
DispathcerServlet –> HandlerMapping –> Controller 方法 –> ModelAndView –> ViewResolver –> 渲染 –> DispatcherServlet // 返回视图
方法区OOM
方法区保存的是Class文件和Meta的相关信息,有类名,访问修饰符,常量池,字段描述,方法描述等。当运行时产生大量的类时就很容易发生OOM(动态代理).
线程池原理
除了ScheduledThreadPool的实现原理有点不同,其余几个都是通过 ThreadPoolExecutor 来实现的. ThreadPoolExecutor 内部是通过一个 AtomicInteger 的变量 ctl 来控制, 这个变量的前三位是用来表示线程词的运行状态,后29位表示当前安线程池的数量.