文章目录
- 引言
- 一面
- 准备
- 面试预演一
- 1、讲一下hashcode()和equals()关系
- 2、equals()和==有什么区别
- 3、讲一下重载和重写的区别
- 4、讲一下深拷贝、浅拷贝的区别
- 5、讲一下Java异常的基类,运行时异常举几个例子,什么情况下会出现?
- 6、讲一下Java中线程的几种状态?以及如何进行切换的?
- 7、讲一下sleep和wait的区别
- 8、介绍一下Java中的乐观锁和悲观锁?
- 9、介绍一下CAS原理?哪些操作使用到了CAS?CAS操作是否有原子性?如何规避ABA问题?
- 10、介绍一下公平锁和非公平锁?举一个具体的实现例子。
- 11、了解死锁吗?如何避免死锁?怎么解除死锁?
- 12、线程池适合什么场景?举几个例子。
- 13、讲一下什么数据适合做索引
- 14、最左匹配原则:针对联合索引(a,b,c,d), where a=2 and b=3 and c > 4 and d = 5用了什么索引
- 15、讲一下项目中遇到的慢SQL 是怎么排查的,后面是怎么解决的?
- 16、SQL事务了解吗,并发情况下会有什么问题 简单介绍一下
- 17、 当前有一个表 想要查询 第二高薪资的员工,怎么用一个sql写出来
- 18、最大连续子序列
- 面试预演二——这里写了,但是没有自动保存,给我清空了!
- Spring中面向切面编程,在项目中是否使用过AOP
- 查数据库响应慢怎么排查
- 正式面试-有点懵,测评没做就约了
- 1、Java中类加载的全过程?
- 2、有哪些类加载器?
- 3、说一下双亲委派模型?双亲委派模型具体是怎么实现的?
- 4、可以自己定义一个String类,去覆盖JDK里面的类吗?
- 5、String类可以继承并且重写吗?
- 6、异常分哪几种?
- 7、运行时异常时怎么触发的?
- 8、try-catch中的finally是干什么的?
- 9、HashMap和HashTable的区别?
- 10、在性能方面有什么折中的方案吗?
- 11、锁的升级过程是怎么样的?
- 12、Synchronized本身是怎么实现的?——监视器锁(monitorenter和monitorexit指令)
- 13、死锁一般怎么形成的?
- 14、程序里面出现了死锁,怎么定位?怎么排查?
- 15、设计模式有几种分类?
- 16、JDK或者其他的开源代码中,哪些地方用到了设计模式?用了什么设计模式?
- 17、进程之间的通信有哪几种方式?
- 18、你在开发中使用过的多进程之间的通信?
- 19、说一下流量控制和拥塞控制?
- 流量控制
- 拥塞控制
- 20、epoll和select的区别?
- 21、手撕算法
- 二面
- 二面预演一
- 二面正式——7/30
- 总结
引言
- 已经收到了测评,准备这周填写测评,然后下周再去约面试。现在就自己过一下网上的面经内容。
- 多准备一下,害怕被拷打!
一面
准备
面试预演一
- 下述面试题来源
- 作者:John_YAN
- 链接:https://www.nowcoder.com/feed/main/detail/85e798bacd5c455a950f268cbcae0fad
- 来源:牛客网
1、讲一下hashcode()和equals()关系
- equals
- 用来判断两个对象是否相等,默认情况下是比较两个对象的内存地址是否相等。
- hashcode
- 返回对象的散列码,默认是返回对象内存地址转换后的整数值。
- 两者的关系
- equals和hashcode共同作用,才能保证对象在基于hash的集合数据结构中的正确行为。
- 两个对象是相等的,equals相等的,返回的哈希值必须相等
- 哈希值相等,但是并不一定相等,因为不相等的对象会放在哈希值相同的两个桶中。
2、equals()和==有什么区别
-
equals
- 用来判断两个对象是否相等,默认情况下的比较两个对象内存地址是否相等。
-
==
- 比较两个对象引用是否指向同一个内存地址,适用于基本数据类型和引用数据类型。
3、讲一下重载和重写的区别
- 重载
- 同一个类中,存在多个方法名相同,但是参数列表或者返回类型不同的方法。
- 重写
- 子类重新定义从父类继承的方法,方法名、参数列表和返回类型都是相同的,用于实现类的多态。
4、讲一下深拷贝、浅拷贝的区别
-
深拷贝
- 创建一个新的对象,递归复制原对象中的所有引用字段指向的对象,新对象和原对象完全独立。
-
浅拷贝
- 创建一个新的对象,直接复制原对象的基本数据类型字段,对于原对象中的引用类型数据,仅仅复制引用。两者的引用字段都是指向的同一块内存区域。
5、讲一下Java异常的基类,运行时异常举几个例子,什么情况下会出现?
- 所有异常都是从Throwable类派生的,其有两个子类,分别是Eror和Exception,
- Exception类是程序本身可以捕获和处理的异常,分为可检出异常和不可检测出异常。
- 可检测异常,是由编译器强制检测的异常,必须要显示处理,常见的包括
- IOException
- SQLException
- ClassNotFoundException
- 不可检测异常是 编译器不会强制检测,可以不处理
- RuntimeException
- NullPointerException空指针
- ArrayIndexOutOfBoundsException数据越界
- ArithmeticException算术异常等
- RuntimeException
6、讲一下Java中线程的几种状态?以及如何进行切换的?
- new状态
- 线程刚创建,还没有start
- runnable状态
- 创建了之后调用start方法
- blocked状态
- 获取锁发现被别人占用了,陷入阻塞
- waiting状态
- 主动调用的wait函数或者join函数,陷入沉睡
- time-waiting状态
- 线程适应wait(time)或者sleep等方法时
- terminated状态
- 线程完成执行,正常退出,或者发生了未捕获的异常死亡
7、讲一下sleep和wait的区别
-
sleep
- 让正在执行的线程暂停执行一段时间
- Thread类的静态方法,不会释放锁,陷入沉睡time_waiting状态,不需要在所里面使用
-
wait
- Object类的实例方法,让线程等待,直到被唤醒或者到时间
- 需要配合锁使用,会释放锁,陷入waiting状态,需要notify或者notifyall唤醒
Java中的锁
8、介绍一下Java中的乐观锁和悲观锁?
- 悲观锁
- 每次拿数据时,都假设别人会修改数据,所以都会对需要访问的资源进行上锁。做操作之前,先上锁。
- synchronized关键字
- 乐观锁
- 每次拿数据时,假设别人不会修改数据,所以不会上锁,但是修改数据时会判断一下别人是否更新过数据,使用版本号等机制实现。读多写少的情况。
- Java中的atomic类是使用乐观锁实现的。
9、介绍一下CAS原理?哪些操作使用到了CAS?CAS操作是否有原子性?如何规避ABA问题?
- CompareAndSwap,通过CAS来保证原子性,底层是通过系统硬件级别实现的。
- 通过比较三个参数(V,expect,update),V是需要修改的变量,expect是期望的值,update是需要更新的值。
- 通过版本号来规避ABA问题,使用AtomicStampedReference来解决ABA问题。
10、介绍一下公平锁和非公平锁?举一个具体的实现例子。
- 公平锁
- 按照线程申请的顺序,获得锁。
- 性能较差,因为需要维护同步队列,线程进行频繁的状态转换和上下文切换,执行速度慢。
- 非公平锁
- 是按照随机或者优先级,分配给申请的线程锁。
- 性能更好,会导致部分线程处于饥饿状态
11、了解死锁吗?如何避免死锁?怎么解除死锁?
- 死锁定义
- 两个或者以上的线程,由于相互竞争资源或者通信造成的阻塞线程,没有外力,无法推进
- 避免死锁的方式
- 避免一个线程同时获得多个锁
- 避免一个线程在一个锁内同时占有多个资源,每一个锁尽量只有一个资源
- 尝试使用定时锁
- 解除死锁
- 杀死某一个阻塞的线程,释放占有的锁或者资源
12、线程池适合什么场景?举几个例子。
- 这里刚刚看过了,回来解答一下
- 适用的场景
- 管理和复用一组线程的机制,适合处理并发任务,特别是需要频繁创建和销毁线程的场景
- 例子
- web服务器,每一个http请求对应一个线程处理,不随着链接建立和删除销毁和创建线程。
- 数据库连接池,使用线程池管理多个并发的数据库查询请求
- 异步任务执行,定时任务调度,消息队列处理
- 后台任务处理,日志处理,文件上传和下载
- GUI应用程序,时间处理,后台数据加载
13、讲一下什么数据适合做索引
- 针对select:经常要查看的数据,实现索引覆盖
- 针对where:经常出现在查询条件中,提高查询速度,减少回表查询
- 针对order by:创建索引加快排序操作
- 针对join:如果某咧经常用于表之间的链接操作,创建索引提高链接效率
- 唯一性约束:主键或者满足唯一性约束的列,创建索引必要
- 经常用于范围查询:某列经常用于范围查询
- 注意,不能用来创建索引的列
- 更新频繁的列,低选择性的列(性别等)
14、最左匹配原则:针对联合索引(a,b,c,d), where a=2 and b=3 and c > 4 and d = 5用了什么索引
- 索引复习材料链接
- a=2,b=3,c>4 将会利用联合索引进行加速查询。
- d=5 由于 c>4 是范围查询,因此 d 列不会被索引利用。
15、讲一下项目中遇到的慢SQL 是怎么排查的,后面是怎么解决的?
- 识别慢查询的方式
- 慢查询日志:启用数据库的慢查询日志,记录执行时间超过阈值的SQL语句
- 手动分析:查看日志,找出执行时间长的SQL语句
- 分析慢SQL语句
- EXPLAIN语句,是否全表扫描了,是否使用了高成本索引扫描
- 解决慢SQL
- 分区表
- 对大表进行分区,减少每次查询需要扫描的数据量
- 优化SQL语句
- 重写索引语句,避免索引失效
- 拆分复杂索引为多个简单查询,或者使用子查询来代替
- 分区表
16、SQL事务了解吗,并发情况下会有什么问题 简单介绍一下
-
这个好说,倒背如流,主要分为两个部分,事务的特性,然后是并发的4个问题,以及对应隔离级别的解决问题。
-
事务的4个特性:
- 原子性:一个事务的执行要么全部成功,要么全部失败
- 一致性:事务执行前和事务执行后,数据库的完整性约束不受影响
- 隔离性:不同事务之间互不影响,互不干扰
- 持久性:事务执行完毕后的,对于数据库的修改,对数据库的修改永久保存,不会丢失
-
并发的问题
- 脏读:读到了其他数据还未提交的修改
- 不可重复读:多次在不同时间点读取一个数据,返回不同的结果
- 幻读:一个事务在前后两次查询中,读取到的记录数不一样
-
对应隔离界别
- 读未提交:允许事务读取未提交的事务
- 读已提交:事务只有提交,其他事务才能读取,避免了脏读
- 可重复读:同一个事务多次读取的结果一直,解决不可重复读的问题
- 序列化 :全部解决,并发性低。
17、 当前有一个表 想要查询 第二高薪资的员工,怎么用一个sql写出来
有点忘记了,得去好好练习一下!
- 嵌套子查询
SELECT *
FROM employees
WHERE salary = (
SELECT MAX(salary)
FROM employees
WHERE salary < (
SELECT MAX(salary)
FROM employees
)
);
- 窗口函数(这个还不会嘞)
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY salary DESC) AS rank
FROM employees
) ranked_employees
WHERE rank = 2;
18、最大连续子序列
- 题目链接
- 这道题还是有思路的,第一遍遍历保存所有数字出现的情况,第二遍遍历找后续
- 遍历找后续的时候,是从序列的开始找的
class Solution {
public int longestConsecutive(int[] nums) {
// define the map eo store each number
Map<Integer,Boolean> map = new HashMap<>();
for(int x : nums) map.put(x,true);
// traverse the nums to judge the longest seq
int res = 0;
for(int x : nums){
// the previous num exists
if(map.getOrDefault(x - 1,false) == true) continue;
int temp = x + 1;
while(map.containsKey(temp)) temp ++;
res = Math.max(temp - x ,res);
}
return res;
}
}
面试预演二——这里写了,但是没有自动保存,给我清空了!
Spring中面向切面编程,在项目中是否使用过AOP
- AOP概述
- AOP是面向对象编程的一种补充,通过预编译和运行期间动态代理的方式,动态的将代码切入到类的指定方法、指定位置上的编程思想就是面向切面编程
- 能够实现在不修改源码的情况下,为系统中的业务组件添加某种通用功能
- 减少代码的重复性,提高代码的可维护性和可重用性。
- 核心概念
- 切面:切入到指定类或者指定方法的代码片称为切面
- 切入点:切入到哪个类或者那个方法叫做切入点
- 有了AOP,能够将几个类共有的代码,抽取到一个切片中,等到需要时在切入对象中,从而改变其原有的行为。
- 应用场景
- 日志记录:在方法执行前后,记录日志,有助于追踪和性能分析
- 权限控制:在方法执行前进行权限控制,确保用户具有执行该方法的权限的
查数据库响应慢怎么排查
-
初步定位问题:
- 查看监控系统和日志,是不是资源瓶颈或者网络延迟等其他问题
- 查看慢查询日志,分析其中的SQL语句,找到查询比较慢的
-
深入分析SQL查询
- 使用explain查看具体SQL的执行计划,是否出现的全表索引,索引未命中等问题。
- 索引优化:添加索引,或者修改索引,确保索引命中。或者索引覆盖等优化方式
-
系统资源检查
- 如果内存过小、CPU占用率太高、或者磁盘IO性能不佳等原因导致的,可以考虑升级硬件设备
-
网络和配置检查
- 如果不在一台机器上,看看是不是网络延迟导致的
- 如果在一台机器上,看看是不是数据库
正式面试-有点懵,测评没做就约了
1、Java中类加载的全过程?
这个章节是关于类加载的,我基本上都忘光了,一个都没有答对,这里整理一下,然后在回来回答!
-
加载
- 通过类的全限定名,找到对应二进制字节流文件
- 将二进制字节流文件中的类的静态存储结构加载到方法区中,转为运行时数据。
- 在堆区创建对应的Class对象,作为访问类信息的入口
-
验证
- 检查字节流,防止载入错误或者恶意的字节流文件,导致JVM崩溃
- 验证流程:文本格式验证、符号引用验证、元数据验证、字节码验证等
-
准备
- 为类的静态变量分配内存,并赋默认值或者常量(final static修饰的)
-
解析
- 将符号引用替换为直接引用,能够直接指向引用对象句柄或者指针等
-
初始化
- 直到该阶段,JVM才开始执行类中编写的代码,根据程序员的编码对类的静态变量去赋值,
- 执行类构造方法中的clinit方法
2、有哪些类加载器?
- 有三层类加载器
启动类加载器
- 在JVM启动时创建,加载最核心的类,如Object、String等,使用本地代码,由操作系统实现
扩展类加载器
- 扩展类加载器,复杂加载一些扩展的系统类,比如XML、加密、网络编程等功能类。
应用类加载器
- 系统类加载器,是加载用户类路径上的类库,直接在代码中使用
- 如果没有自定义类加载器,一般情况下,默认类加载器就是应用类加载器。
- 自定义类加载器是通过继承ClassLoader并重写findclass实现的
3、说一下双亲委派模型?双亲委派模型具体是怎么实现的?
- 类加载器具有等级制度,但不是继承关系,分层但非继承,以组合的方式,复用父加载器的功能。
- 除了顶层的启动类加载器之外,其余类加载器都要用自己的父加载器
具体原理
* 一个类加载器收到类加载请求,不会自己去加载,而是把请求委派给父加载器。以此类推,最后所有请求都会到启动类加载器。
* 只有当父类加载器无法完成式,子类加载器才会去尝试加载
4、可以自己定义一个String类,去覆盖JDK里面的类吗?
- 不可以,根绝双亲委派模型,所有构建类的请求最后都会委派到启动类加载器,而启动类加载器已经加载过String类,所以会直接返回已经加载的String类,并不能重新加载一个String类。
5、String类可以继承并且重写吗?
- String类是声明为final的,意味着不能被继承。
- 方法也不能重写。
6、异常分哪几种?
- 所有异常都是从Throwable类派生的,其有两个子类,分别是Eror和Exception,
- Exception类是程序本身可以捕获和处理的异常,分为可检出异常和不可检测出异常。
- 可检测异常,是由编译器强制检测的异常,必须要显示处理,常见的包括
- IOException
- SQLException
- ClassNotFoundException
- 不可检测异常是 编译器不会强制检测,可以不处理
- RuntimeException
- NullPointerException空指针
- ArrayIndexOutOfBoundsException数据越界
- ArithmeticException算术异常等
- RuntimeException
7、运行时异常时怎么触发的?
- 运行时异常是在程序运行过程中由逻辑错误或意外情况触发的异常类型。常见的运行时异常包括NullPointerException、ArrayIndexOutOfBoundsException、ArithmeticException等。尽管运行时异常不需要显式捕获或声明,但合理地处理这些异常可以提高程序的健壮性和用户体验。通过使用try-catch块捕获异常、提前检查条件和选择适当的数据结构和方法,可以有效地管理运行时异常。
8、try-catch中的finally是干什么的?
- finally块用于在异常处理代码块中执行一些重要的清理操作。
- 无论try块中的代码是否抛出异常,无论是否有catch块处理异常,finally块中的代码都会被执行。
- 它通常用于释放资源,例如关闭文件、网络连接、数据库连接等,以确保程序的稳定性和资源的正确管理。
9、HashMap和HashTable的区别?
线程安全性
- HashMap不是线程安全的,如果要实现多线程同步访问,必须要使用同步机制,保证访问不出错。
- Hashtable是线程安全的,所有方法都是同步的,使用Synchronized关键字实现
null值
- HashMap允许一个key为null,多个value为null
- Hashtable不允许key和value为null
性能
- Hashtable由于所有方法都是要同步,所以性能较低
- HashMap在单线程环境下,性能更好。
10、在性能方面有什么折中的方案吗?
读写锁
- ReentrantReadWriteLock读写锁,能够保证数据在读的情况下,多线程共同访问,但是写时,进能保证一个线程互斥访问。
ConcurrentHashMap
- ConcurrentHashMap引入了分段锁(segment),减少了锁的粒度,从而提高了并发性能。
- 允许更高的并发度,因为它只在必要时对部分Map进行加锁。
- 读操作通常是无锁的,写操作仅对相关的分段进行锁定。
11、锁的升级过程是怎么样的?
- Synchronized的锁升级
- 无锁状态:
- 没有线程持有该锁
- 偏向锁
- 仅有一个线程持有该锁,不会发生竞争
- 轻量级锁:
- 多个线程竞争,但是没有阻塞,会才有自旋的方式来等待
- 重量级锁
- 自旋失败后仍不能获得锁,就膨胀为重量级锁,线程进入阻塞状态,等待操作系统调度恢复!
- 无锁状态:
12、Synchronized本身是怎么实现的?——监视器锁(monitorenter和monitorexit指令)
这个一下子一点都没有想起来,尴尬了,当时还说是Java底层实现的!
-
synchronized关键字在JVM中是通过monitor(监视器)实现的。
- 每个对象都有一个监视器锁。
- 当一个线程进入synchronized方法或代码块时,它会尝试获取这个监视器锁。获得锁的线程可以继续执行,否则它将进入阻塞状态,直到锁被释放。
-
JVM通过两个字节码指令monitorenter和monitorexit来实现synchronized块的功能:
13、死锁一般怎么形成的?
- 定义
- 多个线程因为相互等待对方释放持有的资源而陷入的阻塞状况。
- 死锁生成条件
- 资源互斥访问
- 线程持有资源不可剥夺
- 线程持有资源等待
- 多个线程形成循环等待的情况
14、程序里面出现了死锁,怎么定位?怎么排查?
这个问题太小众了,不应该呀!
通过代码审查
- 确保所有线程获取锁的顺序是一致的,避免不同线程按照不同的顺序获取多个锁。
日志记录
- 在获取锁和释放锁的地方添加详细的日志,记录线程IO、锁ID和时间戳等信息。
- 通过分析日志,可以帮助我们找到那些线程在什么时间点请求了哪些锁?以及是否出现了等待循环。
使用工具jVisualVM
- 监控和性能分析工具,能够提供线程的实时状态,包括死锁检测。
15、设计模式有几种分类?
主要有三种分类模式,分别是
-
创建型模式
- 定义:
- 关注对象的创建方式,通过封装实例化过程,使得系统在不指定具体类的情况下创建对象。
- 常见模式
- 单例模式
- 工厂模式
- 抽象工厂模式
- 定义:
-
结构型模式
- 定义
- 关注类和对象的组合方式,确保系统在复杂性增加时,仍旧可以维护和扩展
- 常见模式
- 适配器模式、桥接模式、装饰器模式、代理模式
- 定义
-
行为型模式
- 定义
- 关注对象之间的责任分配和交互,用于描述对象和类之间的如何协作完成任务
- 常见模式
- 观察者模式、模板模式
- 定义
16、JDK或者其他的开源代码中,哪些地方用到了设计模式?用了什么设计模式?
单例模式的应用
- java.lang.Runtime中的getRuntime()
- java.lang.System内部使用的时单例模式
- java.lang.Desktop通过getDesktop()提工单一实例
工厂模式
- java.util.Calender中的getInstance方法
建造者模式
- StringBuilder和StringBuffer提供动态构建字符串的能力
适配器模式
- Arrays.asList将数组适配为List接口
迭代器模式
- java.util.iterator迭代器模式
Spring中的依赖注入
- 使用工厂模式和单例模式来管理Bean的创建和生命周期
Spring中的AOP
- 通过代理模式来实现横切关注点
17、进程之间的通信有哪几种方式?
管道
- 管道是一种用于进程间通信的机制,主要用于父子进程之间的数据传输。
消息队列
- 消息队列是一种基于消息传递的进程间通信方式。
- 特点:允许一个或多个进程将消息发送到队列中,并允许一个或多个进程从队列中读取消息。消息可以带有类型。
共享内存
- 共享内存是最快的进程间通信方式,因为进程间共享一块内存区域。
- 允许多个进程直接读写这块共享内存。需要配合其他同步机制(如信号量)使用,确保数据一致性。
信号量
- 信号量是一种用于进程间同步的机制,但也可以用于进程间通信。
信号
- 信号是一种用于通知进程某个事件发生的机制。
18、你在开发中使用过的多进程之间的通信?
- 没有
19、说一下流量控制和拥塞控制?
- 大概说了一下,但是语言组织能力不够完善!
流量控制
-
目的
- 防止发送方以过快的速度发送数据,超过接收方的处理能力,避免接收方缓冲区溢出。
-
常见方法
- 停止等待协议
- 发送方发送一个数据包之后,必须等待接收方确认后,才可以发送下一个数据包
- 特点:
- 实现简单,可靠性要求高
- 信道利用率低,
- 滑动窗口协议
- 1、发送方可以连续发送多个数据包,不用等待每一个数据包的确认,直到达到窗口大小
- 2、接收方通过ACK通知发送方接受情况,接收方窗口大小,发送方根据ACK调整窗口滑动以及发送速率
- 特点
- 提高了利用率,适合高速链路
- 窗口大小由接收方决定,可以动态调整
- 停止等待协议
拥塞控制
-
目的
- 防止网络中的过多数据导致路由器或者网络节点的拥塞
-
常见方法
- 慢启动
- 拥塞窗口从最小值开始,收到一个ACK就增加一个MSS
- 拥塞窗口大小快速增长,直到达到慢启动阈值或者出现丢包
- 拥塞避免
- 当拥塞窗口达到阈值的时候,进入拥塞避免阶段
- 每次完整往返增加一个MSS,线性增长,避免突然增加导致网络拥塞
- 快重传
- 发送方接收到三个重复的ACK时,假设丢包,立刻重传丢失的数据包,不必等到超时。
- 快恢复
- 发送放在快速重传之后,不进入慢启动,减少拥塞窗口为慢启动的一半,并进入拥塞避免阶段。
- 慢启动
总结一下,方便记忆
- 慢慢启动,慢慢增加,出现丢包,拥塞避免,再丢包,说明更加拥塞了,先解决当前问题,快速重传。重传之后,快速恢复网络,执行快速恢复算法,直接调低当前速度为慢重传阈值的一半,直接进入拥塞避免装填。
- 两次判断条件
- 第一次丢包,出现阻塞现象,从慢启动进入拥塞避免状态
- 第二次丢包,先快重传,解决当前问题,然后快恢复,直接减到阈值一半,再次拥塞避免算法。
20、epoll和select的区别?
这里一点都没看,当时说这两个关键词的时候,我都懵了,这里暂时先停在这,明天把这个章节补齐了,在开始往下做!
Select方式
- 实现机制
- 使用一个固定大小的数组,来存储文件描述符
- 每次调用select的时候,需要将所有的文件描述符传递给内核,内核遍历所有描述符,确定那些描述符准备好了
- 性能
- 在文件描述符数量增加的时候会下降,因为需要线性扫描所有描述符
epoll方式
-
实现机制
- 使用一个内核事件表来管理多个文件描述符,通过epoll_ctl系统调用注册感兴趣的事件
- 应用程序只需要告诉内核一次他感兴趣的文件描述符和事件类型后,内核通过高效的数据结构管理这些描述符
-
性能
- 文件描述符数量增加的时候性能较好,采用事件驱动机制,只有文件描述符状态变化时才通知应用程序
- 没有文件描述符数量限制,适合处理大量并发连接场景
21、手撕算法
- 链表相交节点
- 最低时间复杂度实现
- 最低空间复杂度实现
刚好整理过,还是比较简单!
二面
二面预演一
二面正式——7/30
总结
- 期待着,期待着,先好好准备吧!
- 通过面试,发现我说的太急了,太快了,太紧张了,完全没有必要!导致整个人会听起来比较慌张!
- 整理完了,终于整理完了,明天开始继续刷题吧!