牛客Java后端面经分析(三)
OS
cpu调度算法
进程线程区别
计网
TCP握手挥手
tcp如何实现可靠传输
java
线程安全的实现方法
hashmap的put操作,时间复杂度
数据库
如何设计好的索引
where a>10 and b=1 and c=2会使用索引么,使用了几个索引
ACID
隔离级别
RR隔离级别下解决幻读 next-key lock和间隙锁
写个sql
项目
rpc框架
注册中心的作用
哈希一致性负载均衡
如何理解序列化
客户端能否自由选择使用的序列化协议?
算法
合并有序链表
口述lru实现
CPU的调度算法
CPU调度即进程调度算法,当CPU空闲时,操作系统就选择内存中某个处于就绪状态的进程,并给其分配CPU
调度算法有抢占式和非抢占式两种,非抢占式当进程运行时就会一直运行,直到该进程完成或者某个事件而阻塞时,才会把CPU让给其他进程,抢占式就是进程运行时会被其他进程打断,一般打断原则有时间片原则,优先权原则,短作业优先原则
说说常见的调度算法:
- 先来先服务调度算法
- 最短作业优先调度算法
- 高响应比优先调度算法
- 时间片轮转调度算法
- 最高优先级调度算法
- 多级反馈队列调度算法
进程线程的区别
- 进程是CPU资源分配的基本单位,线程是CPU调度的基本单位
- 线程共享本进程的地址空间,而进程之间是独立的地址空间。
- 进程拥有完整的资源平台,线程只独享必不可少的资源
- 线程能减少并发执行的事件和空间开销
还有经常会问的协程:协程运行在线程之上,当一个协程执行完成后,可以选择主动让出,让另一个协程运行在当前线程之上。协程并没有增加线程数量,只是在线程的基础之上通过分时复用的方式运行多个协程,无需系统内核的上下文切换,减小开销,无需原子操作锁定及同步的开销,不用担心资源共享的问题,单线程即可实现高并发,单核 CPU 即便支持上万的协程都不是问题,所以很适合用于高并发处理,尤其是在应用在网络爬虫中
TCP的三次握手和四次挥手
三次挥手为什么不是两次:
- 从逻辑上,三次挥手才能让客户端和服务器都确认好自己的收发功能的正常
- 防止历史连接:如果是两次,当client发送SYN,server收到后就会进入建立连接状态,但是这个SYN可能是历史连接,所以服务器白白建立一个无用的连接,造成资源的浪费
- 同步序列号:保证双方的序列号都被对方成功接收,其实和第一点类似
四次挥手的原因:
- 简单来说,客户端发送FIN,仅仅代表客户端可以断开连接了,服务器可能还需要一些处理过程,所以服务器会先回一个ACK(体现TCP作为可靠协议的”可靠“)进入CLOSE_WAIT状态
- TCP连接是全双工的,因此每个方向都必须单独进行关闭
为什么需要TIME_WAIT状态:
该状态是主动断开方收到对方的FIN时进入的状态
- 防止历史连接数据影响后续连接:可能有数据还在网络中游荡,理论上的最长时间为2MSL,所以等这么长时间来接收一些可能还在游荡的数据,避免他的序列号刚好能和下次连接的序列号匹配上,影响下次连接的数据传输(因为序列号无法判断数据的新旧)
线程安全的实现
- 同步互斥:保证临界区数据同一时间只有一个线程能够访问到,悲观并发策略
- 非阻塞同步:乐观锁机制,快速失败,失败重试来访问数据,CAS操作
- 无同步方案:线程本地存储,类如ThreadLocal技术
hashmap的put操作,时间复杂度
首先找到桶位置的时间复杂度为O(1),因为是通过hash实现的
桶位置无元素,是O(1),
如果有小于6个使用尾插法,O(N)
大于6个,O(logN)