JAVA面试点2
CREATED: 2021-02-28 15:00
production 生产环境
devops 运维开发
https://www.bilibili.com/video/BV1AZ4y1379A?p=2&spm_id_from=pageDriver
CPU从内存里面读取指令和数据
工作线程数是不是设置的越大越好?不是 线程切换会有一定的开销
工作线程数设置多少合适?Ncpu * Ucpu * (1 + W/C) = 处理器核的数目 * 期望cpu利用率 * (1 + 等待时间/计算时间比率)
W/C 根据压测来预估推算
线程撕裂者:一个计算单元对应多个可以保存线程的寄存器 节省线程切换时间
ThreadLocal 线程本地变量
线程本地缓存 L1 L2 L3 在cpu中,先去L1, 再去L2,L3,如果都没有最后去内存读。
缓存行:一次性读的一块的数据,64Bytes。同一航数据被不同cpu缓存,需要同步机制:缓存一致性协议。MESI
前后都有7个无意义的long类型数据:保证不与其它要修改数据在同一缓存行。
并发编程三大特性
1. 可见性
2. 有序性: 程序可以乱序执行,保证单线程最终一致性。
3. 原子性
synchronized: 保证线程可见性,把CPU缓存内容刷到内存中。
2021/03/16
僵尸进程
一个进程结束自己的时候,其实它并没有真正的被销毁,因为它的父进程没安装SIGCHLD信号处理函数调用wait或waitpid等待子进程结束,其保留的那段信息就不会释放,其进程号就会一直被占用。
任何一个子进程(init除外)在exit()之后,并非马上就消失掉,而是留下一个称为僵尸进程(Zombie)的数据结构,等待父进程处理。这是每个子进程在结束时都要经过的阶段。如果子进程在exit()之后,父进程没有来得及处理,这时用ps命令就能看到子进程的状态是“Z”。
解决办法:杀死僵尸进程的父进程(僵尸进程的父进程必然存在),僵尸进程成为"孤儿进程",过继给1号进程init,init始终会负责清理僵尸进程。
线程死锁
线程死锁的原因
1 互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求该资源,则请求者只能等待,直至占有该资源的进程用毕释放。
2 请求与保持条件:指进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源又被其它进程占有,此时请求进程阻塞,但又对自己获得的其它资源保持不放。
3 不剥夺条件:指进程已获得资源,在使用完之前,不能被剥夺,只能在使用完时由自己释放。
4 环路等待条件:指在发生死锁时,必然存在一个进程—资源的环形链,即进程集合(P0,P1,P2,…,Pn)中的P0正在等待一个P1占用的资源;P1正在等待一个P2占用的资源,……,Pn正在等待已被P0占用的资源。
解决方法
破坏互斥条件:无法做到
破坏请求与保持条件 : 一次性申请所有的资源。
破坏不剥夺条件: 占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。
破坏循环等待条件: 靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件。
2021/04/17
Thread中的run和start
调用start方法方可启动新线程,而run方法只是thread的一个普通方法调用,还是在主线程里执行。
start() 实现了多线程,run()没有实现多线程。
启动线程的三种方式
1 继承Thread
2 实现Runnable
3 通过线程池来启用 Executors
sleep join yield wait
1.sleep:Thread类的方法,必须带一个时间参数。会让当前线程休眠进入阻塞状态并释放CPU,但不释放锁资源。
2.yield:Thread类的方法,让出CPU调度,类似sleep只是不能由用户指定暂停多长时间 ,并且yield()方法只能让同优先级的线程有执行的机会。 yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。
3.join:当前运行线程调用另一个线程的join方法,当前线程进入阻塞状态直到另一个线程运行结束。
4.wait():让出CPU资源和锁资源。Object类的方法(notify()、notifyAll() 也是Object对象),必须放在循环体和同步代码块中,执行该方法的线程会释放锁,进入线程等待池中等待被再次唤醒。
synchronized
可重入锁
object:不能用String常量,Integer, Long
锁升级:偏向锁,自旋锁,重量级锁(向操作系统申请)。
自旋锁 : 占cpu 但不访问操作系统,仅用户态,不经过内核态。适合执行时间短,线程数目少的情况。
volatile
1 保证线程可见性MESI 缓存一致性协议
2 禁止指令重排序
但是不能保证原子性
CAS
Compare And Set 比较并设置
cas(V, ExpectedValue, NewValue)
if V == E then V = New;
else retry or fail;
CPU原语支持
AtomicStampedReference 版本号解决ABA问题 - object问题
2021/07/21
try catch finally 中遇到的return问题
不管有没有出现异常,finally块中代码都会执行;当try和catch中有return时,finally仍然会执行。
如果有finally代码块,不管有没有异常,finally中的代码都会执行。当try、catch中有return时并没有返回运算之后的值,而是把值保存起来,继续执行finally中的代码,不管finally中对该值有没有做改变,返回的值都不会改变,依然返回保存起来的值。finally代码中最好不要包含return,程序会提前退出,也就是说返回的值不是try或catch中的值。finally中有return语句则直接返回退出,无法执行后面的语句。
finally里的语句只有两种情况下,会不被执行。一种是,在try-catch语句之前,程序就结束了或者挂掉了。第二种是遇到System.exit();
source - https://cloud.tencent.com/developer/article/1694051
堆内存:年轻代+老年代,统称为堆,可设置大小
年轻代分为三块:年轻代(eden区)、S1区、S2区(survivor区),默认情况下,新生代:S1:S2比例是8:1:1。
B+树和B树区别
B树的非叶子节点存储实际记录的指针,而B+树的叶子节点存储实际记录的指针
B+树的叶子节点通过指针连起来了, 适合扫描区间和顺序查找。
2021/08/03
@SneakyThrows
作用于方法上,相当于把方法内的代码添加了一个try-catch处理,捕获异常catch中用Lombok.sneakyThrow(e)抛出异常。使用@SneakyThrows(XXXException.class)指定抛出具体异常。
public void run() {
try {
throw new Throwable();
} catch (Throwable t) {
throw Lombok.sneakyThrow(t);
}
}

浙公网安备 33010602011771号