【面试题】语言基础-2

4、请你说一下Java中的异常处理机制.py
异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行。异常处理机制为:抛出异常,捕捉异常。
一般情况下,在Python无法正常处理程序时就会发生一个异常。
异常是Python对象,表示一个错误。
当Python脚本发生异常时我们需要捕获处理它,否则程序会终止执行。
常见异常:
NameError :未声明/初始化对象 (没有属性)
SyntaxError :Python 语法错误
IndentationError :缩进错误
ValueError :传入无效的参数
SyntaxWarning :可疑的语法的警告

1、 Python 的异常机制
主要依赖 try 、except 、else、finally 和 raise 五个关键字:
a) try 关键字后缩进的代码块简称 try 块,它里面放置的是可能引发异常的代码;
b) 在 except 后对应的是异常类型和一个代码块,用于表明该 except 块处理这种类型的代码块;
c) 在多个 except 块之后可以放一个 else 块,表明程序不出现异常时还要执行 else 块;
d) 最后还可以跟一个 finally 块,finally 块用于回收在 try 块里打开的物理资源,异常机制会保证 finally 块总被执行;try-finally 语句无论是否发生异常都将执行最后的代码。
e) raise 用于引发一个实际的异常,raise 可以单独作为语句使用,引发一个具体的异常对象;可以使用raise语句自己触发异常

2、使用try…except捕获异常
如果在执行 try 块里的业务逻辑代码时出现异常,系统自动生成一个异常对象,该异常对象被提交给 Python 解释器,这个过程被称为引发异常。
当 Python 解释器收到异常对象时,会寻找能处理该异常对象的 except 块
 如果找到合适的 except 块,则把该异常对象交给该 except 块处理,这个过程被称为捕获异常。
 如果 Python 解释器找不到捕获异常的 except 块,则运行时环境终止,Python 解释器也将退出。

3、 try的工作原理
当开始一个try语句后,python就在当前程序的上下文中作标记,这样当异常出现时就可以回到这里,try子句先执行,接下来会发生什么依赖于执行时是否出现异常。
 如果当try后的语句执行时发生异常,python就跳回到try并执行第一个匹配该异常的except子句,异常处理完毕,控制流就通过整个try语句(除非在处理异常时又引发新的异常)。
 如果在try后的语句里发生了异常,却没有匹配的except子句,异常将被递交到上层的try,或者到程序的最上层(这样将结束程序,并打印默认的出错信息)。
 如果在try子句执行时没有发生异常,python将执行else语句后的语句(如果有else的话),然后控制流通过整个try语句。

4、Python 异常使用规范
不要过度使用异常
把异常和普通错误混淆在一起,不再编写任何错误处理代码,而是以引发异常来代替错误处理。
使用异常处理来代替流程控制。
不要使用过于庞大的 try 块
在 try 块里放置大量的代码,然后紧跟大量的 except 块,增加了编程复杂度。
不要忽略捕获到的异常
处理异常。对异常进行合适的修复,然后绕过异常发生的地方继续运行;或者用别的数据进行计算,以代替期望的方法返回值;或者提示用户重新操作……总之,程序应该尽量修复异常,使程序能恢复运行。
重新引发新异常。把在当前运行环境下能做的事情尽量做完,然后进行异常转译,把异常包装成当前层的异常,重新传给上层调用者。
在合适的层处理异常。如果当前层不清楚如何处理异常,就不要在当前层使用 except 语句来捕获该异常,让上层调用者来负责处理该异常。

https://www.runoob.com/python/python-exceptions.html
https://www.jianshu.com/p/0ba916b753fa

5、请问多线程是什么?
多线程是为了同步完成多项任务,不是为了提高运行效率,而是为了提高资源使用效率来提高系统的效率。线程是在同一时间需要完成多项任务的时候实现的。
一个采用了多线程技术的应用程序可以更好地利用系统资源。其主要优势在于充分利用了CPU的空闲时间片,可以用尽可能少的时间来对用户的要求做出响应,使得进程的整体运行效率得到较大提高,同时增强了应用程序的灵活性。更为重要的是,由于同一进程的所有线程是共享同一内存,所以不需要特殊的数据传送机制,不需要建立共享存储区或共享文件,从而使得不同任务之间的协调操作与运行、数据的交互、资源的分配等问题更加易于解决。
线程在执行过程中与进程还是有区别的。每个独立的进程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
进程,CPU进行资源分配和管理的最小单元;
线程,CPU进行调度的最小单元。
进程拥有一个完整的虚拟地址空间,不依赖于线程而独立存在;反之,线程是进程的一部分,没有自己的地址空间,与进程内的其他线程一起共享分配给该进程的所有资源。

Python中使用线程有两种方式:函数或用类来包装线程对象。
函数式:调用thread模块中的start_new_thread()函数来产生新线程。

Python通过两个标准库thread和threading提供对线程的支持。thread提供了低级别的、原始的线程以及一个简单的锁。threading 模块提供的其他方法。

https://www.runoob.com/python/python-multithreading.html

6、请你来聊一聊集合类和内存.py
在 Python 中,集合分为两类:
set:可变集合,可以原地修改,或者说是可变的,也可以说是 unhashable(不可哈希)的。
frozenset:不可变集合,不能原地修改,是 hashable(可哈希)的。

Python 中一切皆对象,对象又可以分为可变对象和不可变对象。二者可以通过原地修改,如果修改后地址不变,则是可变对象,否则为不可变对象,地址信息可以通过id()进行查看。
Python 有内存池机制,Pymalloc机制,用于对内存的申请和释放管理。内存池的概念就是预先在内存中申请一定数量的,大小相等的内存块留作备用,当有新的内存需求时,就先从内存池中分配内存给这个需求,不够了之后再申请新的内存。这样做最显著的优势就是能够减少内存碎片,提升效率。
查看源码,可以看到 Pymalloc 对于小的对象,Pymalloc会在内存池中申请空间,一般是少于236kb,如果是大的对象,则直接调用 new/malloc 来申请新的内存空间。

7、请你说一下java jvm的内存机制
Python的内存管理机制:引入计数、垃圾回收、内存池机制

8、请你说一说有哪几种垃圾回收算法(T3)

9、请你说一说垃圾收集机制(T3)
10、请你回答一下GC Root可以是哪些
**
GC(Garbage Collector) Roots 实际上是垃圾回收器需要回收的对象。垃圾回收器回收那些不是 GC Roots 的对象并且不再被GC Roots引用的对象。
1、 虚拟机栈(栈帧中的本地变量表)中引用的对象。
2、 本地方法栈中JNI(即一般说的native方法)引用的对象。
3、 方法区中的静态变量和常量引用的对象。

11、请你说一下OOM可能发生在哪,怎么查看,怎么调优.Py
Out Of Memory,“内存用完了”
引用sys,在使用getsizeof()方法
引用psutil
调优:(1)垃圾回收(2)引用计数(3)内存池机制

12、请你说一下类加载
首先,使用加载模块,使用内置函数提供的反射方法getattr(),依次按照层级获取模块->类\全局方法->类对象\类方法。
动态加载模块:
方式1:系统函数__import__()
方式2:imp, importlib 模块
方式3:exec 函数

13、请你说一下AQS.jv···
AQS:Abstract Quened Synchronizer抽象的队列式同步器。是除了java自带的synchronized关键字之外的锁机制。这个类在java.util.concurrent.locks包

14、请你说一下volatile ···
volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其他线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。

15、请你说一下死锁的原因,以及如何打破,如何查看死锁进程状态
1、死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站用不会释放的资源而处于的一种永久等待状态。死锁的四个必要条件:
 互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。
 请求与保持条件(Hold and wait):已经得到资源的进程可以再次申请新的资源。
 非剥夺条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。
 循环等待条件(Circular wait):系统中若干进程组成环路,该环路中每个进程都在等待相邻进程正占用的资源。
产生死锁可能性的最根本原因是:1)是多个线程涉及到多个锁,这些锁存在着交叉,所以可能会导致了一个锁依赖的闭环;2)默认的锁申请操作是阻塞的。
如,线程在获得一个锁L1的情况下再去申请另外一个锁L2,也就是锁L1想要包含了锁L2,在获得了锁L1,并且没有释放锁L1的情况下,又去申请获得锁L2,这个是产生死锁的最根本原因。
2、避免死锁:
方案一:破坏死锁的循环等待条件。
方法二:破坏死锁的请求与保持条件,使用lock的特性,为获取锁操作设置超时时间。这样不会死锁(至少不会无尽的死锁)
方法三:设置一个条件遍历与一个锁关联。该方法只用一把锁,没有chopstick类,将竞争从对筷子的争夺转换成了对状态的判断。仅当左右邻座都没有进餐时才可以进餐。提升了并发度。
3、linux中查看死锁进程状态
使用pstack 和 gdb 工具对死锁程序进行分析
pstack 进程号 查看各个线程的堆栈信息
当进程吊死的时候,多次使用,死锁的线程将一直处于等锁的状态,确定某些线程一直没有变化,一直处于等锁的状态。那么这些线程很可能是死锁了。如果怀疑哪些线程发生死锁了,可以采用gdb 进一步attach线程并进行分析。
执行命令gdb attach 进程号,进入gdb调试终端
运行:(gdb) info thread

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值