面经问题学习

面经内容整理和学习

1.语言相关

1.1 Python

1.1.1 Python的类方法(实例方法、静态方法、类方法)

这三种方法在Python中都有自己的特征。

在类定义的时候,类内方法的实例方法,通常不需要使用装饰器,并且传参的时候第一项是self关键字。self指的是实例,在调用该类方法的时候,相当于调用了self.func()

而对于类方法的话,通常需要@classmethod装饰器来修饰,并且函数传入的参数必须有类本身,常用cls

对于静态方法的话,需要使用@staticmethod装饰器来进行装饰。并且可以不传入参数。

实例方法静态方法类方法
装饰器@staticmethod@classmethod
参数selfcls
行为将实例作为参数进行传递可以直接通过类或者使用实例调用不与类或实例绑定
场景解决和对象绑定问题管理类中的数据,对数据进行重构验证数据等
1.1.2 进程与线程

多进程

Python使用多进程在Windows端常用模块为multiprocessing,该模块提供了Process类来代表一个进程对象。即创建一个Process实例,然后使用start()方法启动进程。并且常常使用join()方法,该方法保证主进程会等待子进程结束后再执行下一步,常常用于进程间的同步。

同样,若要启动大量子进程,可以使用进程池的方式批量创建子进程,同样,该方法也是用join()方法来等待子程序结束,但是区别是在使用join()之前必须要调用close(),在调用close()后就无法在添加新的进程了。值得注意的是,Pool()的大小取决于CPU的核数。

Python中进程间的通信方法常用QueuePipes方式来实现,其中Queue常用的方法有putget。在使用多线程的时候,往往牵扯到的使用。多线程中所有的变量都由所有的线程共享,任何一个变量都可以被任何一个线程修改。因此,线程之间的共享数据最大的危险在于多个线程同时修改一个变量。为了保证共享数据的安全性,就需要给当前变量操作上一把锁,即当某个进程要执行某些操作时,必须时获得锁的状态。并且此时,别的线程不能同时执行这个操作,除非锁释放了。Python中通常使用threading.Lock()来实现。将其实例化后,可以使用lock.acquire()来获取锁。而且,锁在使用完毕后一定要释放,因此常用try....finally结构。

由于Python中每个线程都会持有自己的局部变量,因此需要传参的时候,代码往往非常冗余。Python提供了ThreadLocal方法,在实例化后得到的对象可以看成全局变量,但是当线程实例使用它时,它对每个线程都是局部变量。

多线程

Python中的多线程主要是靠_threadthreading模块提供,通常使用threading模块,使用时,将一个函数传入并创建Thread实例,然后使用start()开始执行。

1.1.3 多进程+协程的使用以及为何使用

首先,介绍什么是协程:

协程是一种用户级的轻量级线程。协程拥有自己的寄存器上下文和栈。协程调度切换的时候,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此,协程能保留上一次调用时的状态。

用协程的好处在于避开进程、线程的系统调用设计问题,避开抢占式调度执行顺序无法确定的问题。协程是由用户自己来编写调度逻辑的,对CPU来说,它是单线程的,所以CPU不用去考虑怎么调度、切换上下文,甚至不需要多线程的锁机制,省去了CPU的开销。

协程和多线程比较起来有如下优势:

  • 协程执行效率极高,因为子程序切换不是线程切换,而是程序自身控制,没有线程切换的开销,尤其是在线程数量比较多的时候,协程的性能优势就越明显;
  • 不需要多线程的锁机制,因为协程运行的时候相当于单线程,不存在同时写变量的冲突,控制共享资源不需要锁,只需要判断状态就可。

由于协程是单线程,因此要使用多个CPU需要使用到多进程+协程的方式。协程是使用生成器来实现得,在使用时C端向S端通过send()方法传递消息。但是在进行send()操作前,需要将协程进行预激处理,即需要通过next(gen)或者gen.send(None)来激活协程。不过在通常情况下可以直接使用装饰器来进行自动的预激处理,常用的有coroutine()方法。值得注意的是,如果使用yield from来实现的协程,是与这些装饰器冲突的,因为其会自动预激。

协程还有一项任务是终止协程异常处理

协程中未处理的异常会向上冒泡,传给next或者send方法的调用方。因此终止协程可以使用某个哨符值,让协程退出。在Python中提供了在客户代码可以直接调用的方法,generator.throw以及generator.close

使用多进程+协程的原因在于,既可以充分利用多核,又可以充分发挥协程的高效率。

1.1.4 进程通信与线程通信
进程线程
管道
消息队列信号量
共享内存信号
信号
信号量

2.数据库相关

2.1 Mysql

2.1.1 索引
2.1.1.1 索引的实现方式
2.1.1.2 聚簇索引与非聚簇索引

什么是聚簇索引

表数据按照索引的顺序来存储,也就是说索引项的顺序与表中记录的物理顺序一致。对于聚集索引,叶子结点就是存储了真实的数据行的节点,不再有单独的数据页。在一张表上最多只能创建一个聚簇索引。

什么是非聚簇索引

表数据存储与索引顺序无关,对于非聚簇索引,叶结点包含索引字段值及指向数据页数据行的逻辑指针。

总的来说,聚簇索引是一种稀疏索引,数据页上一级的索引页存储的是页指针,而不是行指针。而非聚簇索引是密集索引,在数据页的上一级索引页,它为每一个数据行存储一条索引记录。

2.1.2 事务

事务其实就是由多条数据库操作语句构成的。主要用于处理操作量大、复杂度高的数据。

事务主要拥有四个特性,即ACID:

  • 原子性:操作不可拆分,要么全成功,要么全部失败进行回滚。
  • 一致性:事务开始前和结束后,数据库的完整性没有遭到破坏。总是从一个一致性状态转换到另一个一致性状态。
  • 隔离性:一个事务所做的修改在最终提交前,对其他事务都是不可见的。
  • 持久型:一旦事务提交,则其所做的修改会永久到保存到数据库中。

其中由并发事务带来一系列的问题:

  • 更新丢失:当两个或多个事务选择同一行,然后基于最初选定的值更新行的时候,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题。即最后更新会覆盖由其他事务进行的更新。
  • 脏读:一个事务正在对一条记录进行修改,再还没有提交这次修改之前,另一个事务也来读取这一条数据,若没合适的控制机制,第二个事务就会读取这些不一致状态下的数据。
  • 不可重复读:一个事务在读取某些数据后的某个时间,再次读取该数据,此时读出的数据可能已经发生了变化,或者某些记录已经被删除了。
  • 幻读:一个事务按之前相同的查询条件重新读取之前检索过的数据,却发现其他事务插入了满足其查询条件的新数据。

根据上述问题,SQL标准定义了4类隔离级别:

  • Read Uncommitted(读取未提交内容)

    该级别会引发脏读问题,即读取到未提交的数据。该级别中,所有事物都可以看到其他未提交事务的执行结果。

  • Read Committed(读取提交内容)

    该级别满足了隔离的简单定义,即一个事务只能看见已经提交事务所作的改变。这种隔离方式引发的问题是不可重读。

  • Repeatable Read(可重读)

    Mysql的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据的时候,会看到同样的数据行。这个隔离级别会出现的问题是幻读。通过MVCC和间隙锁解决幻读问题。

  • Serializable(可串行化)

MVCC:多版本并发控制

MVCC是用于Read Committed与Repeatable Read下的控制机制。实际上是保存了数据在某个时间节点的快照。可以理解为对每一个表,都隐藏了两列,这两列的内容分别为create_versiondelete_version。在事务操作过程中,每一条操作语句会对current_version进行更新。MVCC的原理就是查找创建版本小于等于当前事务版本,删除版本为空或者大于当前事务版本的项。

2.1.3 Mysql的常用数据类型
名称类型说明
INT整型4字节整数类型
BIGINT长整型8字节整数类型
REAL浮点型4字节浮点数
DOUBLE浮点型8字节浮点数
CHAR(N)定长字符串指定长度字符串
VARCHAR(N)变长字符串存储可变长度字符
BOOLEAN布尔类型True或False
DATE日期类型存储时间,如2020-12-12
TIME时间类型存储时间,如16:31:22
DATETIME日期和时间类型上面两项的组合
2.1.4 drop、delete与truncate的区别
名称作用
drop直接删掉表
delete删掉的是表中的数据,事务会记录
truncate删除表中数据,可以在后面添加where语句。不会记录,删除行无法恢复。该关键字只能对某个表进行操作。

2.2 数据库设计的三范式

  • 要求有主键,并且要求每一个字段原子性不可再分;

第一范式要求数据库的每一行必须唯一,也就是每个表必须有一个主键。这是数据库设计的最基本要求。

  • 要求所有非主键字段完全依赖主键,不能产生部分依赖;

若违背该范式,会造成数据出现大量的冗余。此时可以改变设计为“多对多”。

  • 所有非主键字段和主键字段之间不能产生传递依赖;

【例子参考】三范式例子

3.计算机网络相关

3.1 Session 和 Cookie

Cookie

Cookie是一段由Server送给使用者浏览器的一小块文档。浏览器储存他,并且在浏览器下次发送请求的时候将他送回原来的服务端。

Cookie是用来区分两个请求是否来自同一个浏览器,以此去保持使用者的登陆状态的方案。

其具备两个特性,并且向domain的服务发送请求的时候,Cookie也会一并在请求中发送:

  • 只针对原本的网段起作用。
  • 有生命周期,到了所设定的生命周期后会失效。

Session

Session负责记录在使用端上的使用者讯息,会在一个用户完成身份认证后,存下所需要的用户资料,接着产生一组对应的ID存入Cookie后,传回客户端。一句话就是Session是账户登陆过后,Sever端所发的识别证。

3.2 HTTP状态码

大方向上区分:

分类描述
1**信息,服务器收到请求,需要请求者继续执行操作
2**成功,操作被成功接收并处理
3**重定向,需要进一步的操作来完成请求
4**客户端错误,请求包含语法错误或者无法完成
5**服务端错误,服务器在处理请求过程中发生错误

具体的常问的:

名称内容
200请求成功,一般用于get和post
301请求的资源被永久移动到的新的url
302临时移动
400客户端请求语法错误
保留,将来使用
服务器理解请求,但是拒绝执行
服务器无法根据客户端的请求找到资源
500服务器内部错误,无法完成请求
502作为网关或者代理工作的服务器尝试请求执行时,从远程服务器接收到一个无效响应

4.设计模式

4.1 单例模式

饿汉式

#include <iostream>

class singleton{
private:
    static singleton* p;
    singleton;
public:
    static singleton * getInstance(){
        return p;
    }
}

singleton* singleton::p = new singleton();

int main(){
    singleton* p = singleton::getInstance();
    singleton* p2 = singleton::getInstance();
    std::cout << p <<std::endl;
    std::cout << p2 << std::endl;
    return 0;
}

饿汉式是线程安全的实现方法,因为p在进入main函数之前就由单线程方式实例化了。

懒汉式

class singleton{
private:
	static singleton* p;
    singleton();
public:
    static singleton* getInstance(){
        if (p == NULL){
            p = new singleton();
            std::cout << "onece" << std::endl;
        }
        else std::cout << "not once" <<std::endl;
        return p;
    }
}

懒汉式存在线程安全问题,必须加锁。

杂项

1. 什么是计算密集型、什么是IO密集型

计算密集型任务:

计算密集型任务的特点是要进行大量的计算,消耗CPU资源,比如计算圆周率、对视频进行高清解码等等,全靠CPU的运算能力。这种计算密集型任务虽然也可以用多任务完成,但是任务越多,花在任务切换的时间就越多,CPU执行任务的效率就越低,所以,要最高效地利用CPU,计算密集型任务同时进行的数量应当等于CPU的核心数。

计算密集型任务由于主要消耗CPU资源,因此,代码运行效率至关重要。Python这样的脚本语言运行效率很低,完全不适合计算密集型任务。对于计算密集型任务,最好用C语言编写。

IO密集型任务:

涉及到网络、磁盘IO的任务都是IO密集型任务,这类任务的特点是CPU消耗很少,任务的大部分时间都在等待IO操作完成(因为IO的速度远远低于CPU和内存的速度)。对于IO密集型任务,任务越多,CPU效率越高,但也有一个限度。常见的大部分任务都是IO密集型任务,比如Web应用。

IO密集型任务执行期间,99%的时间都花在IO上,花在CPU上的时间很少,因此,用运行速度极快的C语言替换用Python这样运行速度极低的脚本语言,完全无法提升运行效率。对于IO密集型任务,最合适的语言就是开发效率最高(代码量最少)的语言,脚本语言是首选,C语言最差。

2.什么是线程安全

线程安全可以简单理解为一个方法或者一个实例可以在多线程环境中使用而不会出现错误。

3. kill -9 与 kill -15的差别

在使用kill -9 or kill -15的时候,实际上是执行Linux中的中止信号。他们的差别主要在于:

kill -9kill -15
立即杀死进程,并且该信号不可被中断、阻塞正常退出进程,该信号可以回调或者阻塞
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码下载:完整代码,可直接运行 ;运行版本:2022a或2019b或2014a;若运行有问题,可私信博主; **仿真咨询 1 各类智能优化算法改进及应用** 生产调度、经济调度、装配线调度、充电优化、车间调度、发车优化、水库调度、三维装箱、物流选址、货位优化、公交排班优化、充电桩布局优化、车间布局优化、集装箱船配载优化、水泵组合优化、解医疗资源分配优化、设施布局优化、可视域基站和无人机选址优化 **2 机器学习和深度学习方面** 卷积神经网络(CNN)、LSTM、支持向量机(SVM)、最小二乘支持向量机(LSSVM)、极限学习机(ELM)、核极限学习机(KELM)、BP、RBF、宽度学习、DBN、RF、RBF、DELM、XGBOOST、TCN实现风电预测、光伏预测、电池寿命预测、辐射源识别、交通流预测、负荷预测、股价预测、PM2.5浓度预测、电池健康状态预测、水体光学参数反演、NLOS信号识别、地铁停车精准预测、变压器故障诊断 **3 图像处理方面** 图像识别、图像分割、图像检测、图像隐藏、图像配准、图像拼接、图像融合、图像增强、图像压缩感知 **4 路径规划方面** 旅行商问题(TSP)、车辆路径问题(VRP、MVRP、CVRP、VRPTW等)、无人机三维路径规划、无人机协同、无人机编队、机器人路径规划、栅格地图路径规划、多式联运运输问题、车辆协同无人机路径规划、天线线性阵列分布优化、车间布局优化 **5 无人机应用方面** 无人机路径规划、无人机控制、无人机编队、无人机协同、无人机任务分配 **6 无线传感器定位及布局方面** 传感器部署优化、通信协议优化、路由优化、目标定位优化、Dv-Hop定位优化、Leach协议优化、WSN覆盖优化、组播优化、RSSI定位优化 **7 信号处理方面** 信号识别、信号加密、信号去噪、信号增强、雷达信号处理、信号水印嵌入提取、肌电信号、脑电信号、信号配时优化 **8 电力系统方面** 微电网优化、无功优化、配电网重构、储能配置 **9 元胞自动机方面** 交通流 人群疏散 病毒扩散 晶体生长 **10 雷达方面** 卡尔曼滤波跟踪、航迹关联、航迹融合

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值