面试题汇总
2020-03-29
11 min read
TCP/IP
《计算机网络原理:自顶向下方法》《TCP/IP详解卷1》《图解TCP/IP》《图解HTTP》
- TCP和UDP的区别和优缺点?
参考 - 三次握手四次挥手的过程
- 三次握手:
- 客户端和服务器都建立TCB
- 客户端向服务端发送TCP报文,其中SYN指针设置为1,消耗一个序列号,进入同步发送状态;不能携带数据。
- 服务端向客户端发送TCP报文,其中SYN指针设置为1,ACK指针设置为1,消耗自己序列号1个,确认序列号为客户序列号加1,进入同步接收状态;不能携带数据。
- 客户端发送,ACK指针设置为1,确认序列号为服务端序列号,此时可以携带数据,如果不发送数据就不消耗序列号。进入已建立状态。
- 服务端收到确认报文后也进入建立状态。
- 四次挥手
- 客户端发送FIN指针为1,序列号为x;进入终止等待1状态;
- 服务端发送ACK指针为1,序列号为y,确认序列号为x+1;服务端进入关闭等待状态;客户端收到时进入终止等待2状态;
- 服务端发送FIN指针为1,FIN=1,ACK=1,seq=z,ack=x+1;服务端进入关闭等待状态;
- 客户端接收后发送一个ACK=1,ack,seq的报文,进入时间等待状态;等待两倍最大报文段寿命后关闭。
- 服务端接收到后直接关闭。
- 三次握手:
- 能不能两次握手
不能。假如客户端发送了一次握手后由于网络延迟原因晚到达,在这期间要是客户端再次发送确认,在服务器收到第二次同步请求时就建立了连接,此时如果第一次同步请求由于网络通畅到达了,那么就会造成两次建立连接,导致不必要的错误或资源浪费。 - 能不能三次挥手
不能。需要服务端传输数据的时间。 - 如果建立连接后客户端故障咋办。
有计数保活器,每次接收到客户端资源都会更新保活器,如果两个小时没接收到,那就发送探测报文端,没75秒发送一个,一连10个都没反应就关闭连接。 - 如何保证可靠性
- 超时重传:有一个定时器,超时没收到确认码就重新传输。
- 数据报检验:端对端的检验,防止到达目的IP后,在分用的时候可能会出现问题。
- 流量控制:通过滑动窗口控制流量
- 拥塞控制:慢开始(一开始就发送大量数据容易拥塞)、拥塞避免 (拥塞窗口缓慢变大)、快速重传和恢复(一个没确认,但后续三个确认了,就迅速重传没确认那个)
- 数据包重排序:
- 停止等待协议:发完一个分组就停止发送,等待对方发送确认码。
2-5参考
- TCP/IP有几层?每一层的作用?MAC地址在哪层?
- 四层:应用层,传输层,网络层,链路层
- 链路层:物理接口方面的,以太网协议,点对点协议
- 有什么应用层协议
HTTP、DNS、DHCP、SMTP - IPv4、IPv6
- 长度不同,一个32位一个128位
- 安全性不同,ipv6可以加密传输
- 路由表大小不同,IPv6的路由表相比IPv4的更小
- IPv6的组播支持以及对流的支持要强于IPv4
- IPv6使用NDP,IPv4使用ARP
- ARP协议
地址解析协议,先查ARP缓存,然后先匹配网络号和子网号,再匹配默认,广播方式发送局域网。 - http状态码
200是请求请求成功,300重定向,400客户端错误,500是服务端错误。 - request和response
request发送请求头,包括方法、URI和协议版本,请求字段,请求主体;response中有响应头,包括协议版本,状态码,状态信息,返回头和主体。
算法
-
数组与链表的区别
- 数组连续存储,链表不连续
- 数组通过下标访问,链表通过结点存放的地址访问
- 数组定长,链表不定长
-
二分查找过程
取中位数进行比较,然后对 -
二叉树遍历方式,后序过程
前序、中序、后序遍历。 -
快排过程
-
二叉树先序遍历和后序遍历结果相同是什么二叉树
只有一个父节点的树 -
双向链表节点删除
-
单链表给两个指针怎么检验是否有环。快慢指针的方式,
-
堆排序为啥不稳定和建堆时间
自上而下建堆是O(nlogn),自下而上是O(n) -
循环队列三种方式
- 设定一个flag,初始化为false,在存的时候为true,取的时候为false
- 设定一个count值
- 空出一个值
Java
- 面向对象的设计要素
- 封装性
- 多态性
- 继承性
- 设计原则
- 单一职责原则(Single Responsibility Principle):一个类只负责一项职责
- 接口隔离原则(Interface Segregation Principle):一个类对另一个类的依赖应该建立在最小接口上
- 依赖倒转原则(Dependence Inversion Principle):高层模块不要依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象;面向接口编程
- 里氏替换原则(Liskov Substitution Principle):在子类中尽量不要重写父类方法
- 开闭原则(Open Closed Principle):对扩展开放,对修改关闭
- 迪米特法则:对象与对象之间应该保持最少的了解;只和直接朋友(成员变量、返回类型、参数类型)通信,即类方法中不要以陌生对象作为局部变量。
- 合成复用原则(Composite Reuse Principle):尽量使用合成或聚合而不是继承。
- Java的基本变量有哪些?类型占用字节?
字符型:char。字节大小:2
布尔型:boolean。Java虚拟机规定为4个字节。
整数型:byte、short、int、long。字节大小:1 2 4 8
浮点型:float、double。字节大小:4 8
空类型:void
内部使用:returnAddress - 构造函数能被重写吗?能被重载吗?子类的super是重写吗?
能被重载,不能被重写。子类的super不是重写,是调用,必须在构造函数的第一行。 - List和Set区别是什么?Set为什么能去重?
- List能存放重复对象,Set不可以
- List有序,Set无序
- HashMap底层原理:bucket扩容?k冲突了怎么办?
扩容是通过复制来的,扩容后的大小为2的幂次方,这跟二次hash计算有关系,然后就是进行拷贝。hash冲突了就先检查bin的第一个node中key值是否相等,如果相等就直接返回,否则就检查第一个node的类型,如果是不是TreeNode,那么就按照链表方式查到链尾,然后添加元素,但是这个时候要判断链长是否超过阈值,默认是8,如果超过了,就将该链转为红黑树;如果检查为TreeNode类型,则直接TreeNode添加结点方法。 - Volatile用过吗?有什么作用?
使对象具备可见性,即当对volatile对象进行写操作时,会更新到主存中,其他线程的读需要到主内存中进行读取,内在原理是内存屏障,因此也能防止指令重排。 - Java内存机制
每个线程有私有栈,方法区存放类(包含静态变量),堆存放对象。 - 接口和抽象类的区别有哪些?里面变量有什么不同吗?方法有什么不同?
- 类继承一个抽象类,却可以实现多个接口
- 抽象类方法有默认实现,接口不存在默认实现
- 抽象类访问修饰符都可以用,接口只能是public
- 都不可以被实例化
- 线程的创建方式有哪几种?创建方法说下?
- 继承Thread,重写run方法
- 实现Callable,重写call方法
- 实现Runable,重写run方法
- String abc = new Stirng("111"),新建了几个对象?abc指向哪?
创建了两个对象,一个在常量池中,一个从常量池拷贝到堆中,abc指向堆中String对象。 - 对象和类的差异
- 常用设计模式
- 创建者模式
- 简单工厂模式,工厂方法模式
- 单例模式
- 结构型模式
- 原型:实现clone
- 适配器:类适配器,方法适配器
- 代理模式:静态代理,动态代理
- 行为者模式
- 策略者(多态)
- 观察者:注册观察者
- 责任链模式:ClassLoader?
- 创建者模式
- 多态了解
- JVM类加载机制
- (1)加载:查找并装载类型的二进制数据
- (2)连接 :验证(四次class验证),准备(类变量分配内存并初始化),解析(符号引用转为直接引用)
- (3)初始化:把类变量初始化为正确的初始值
- GC
分代:young、old - 字节码
操作系统
《深入理解计算机系统》 《Linux内核设计与实现》《深入理解linux内核》《Linux高性能服务器编程》
- 进程间通讯用什么
管道、FIFO、消息队列、信号量、共享内存 - 进程阻塞是怎么做到的
等锁、IO - 多线程是什么
- 有哪些锁分别解释一下
- 乐观锁:认为数据不会被修改,所以不会加锁,只会在更新数据时做检查,通常使用CAS算法
- 悲观锁:认为数据会被修改,加锁。
- 缓存的作用以及缓存替换算法
- 虚拟文件系统
- 进程和线程之间的区别
- 进程:线程是CPU调度的最小单元,切换需要把当前进程寄存器中数据存储到PCB中,然后把切换目标进程PCB中的数据赋值到寄存器中。
- 线程:是进程调度的最小计算单元,共享内存。切换时把当前线程的指令地址指针存放到TCB中,将下个线程TCB中的指令地址指针存放到esp(CPU取值执行所用的寄存器)中
数据库
《MySQL必知必会》《数据库原理,编程与性能》《Redis设计与实现》
数据库
- 索引:B树、B+树底层结构,索引失效条件
- sql语法
- 关系型数据库三范式
- 存储引擎:InnoDB和MyISAM对比
- 数据库的锁:行锁,表锁,页级锁,意向锁,读锁,写锁,悲观锁,乐观锁等等
- 数据库隔离级别,脏读、不可重复读、幻读
- 事务的ACID理论
- 查询优化:explain,慢查询,show profile
- 分布式:分库分表,读写分离
- sql乐观锁悲观锁
Redis相关
《Redis设计与实现》
- Redis 特点
- Redis 底层数据结构:跳表,字典
- 数据淘汰策略
- 持久化方式:AOF,RDB
- 哨兵模式
- 集群同步方式
手撕代码
- Leetcode石头碰撞问题
- 将一整数分别转换成对应的二进制、八进制和十六进制形式
- 将两个分数进行相加并化简成最精简的形式,输入的分数形式为"a / b"(除号两边有空格),a和b为正整数。题目
- 给一个数组找两个数加起来等于给定数
- 字符串最大连续子串
- 删除相邻的重复字符。例:acccaef输出为acaef,accaef输出为ef
- 字符串解码。例:3[a]2[c]输出为aaaccc,3[a2[c]]输出为accaccacc
- 链表节点初始化
- int型数字反向输出(注意溢出问题)
- 完整实现一个双向链表
- 用数组实现深度为100的消息队列,入队出队函数
机考
- 方阵旋转
- 分礼物
- 编辑距离
项目
- 需求分析
- 并发访问的处理
- UML有哪些模型