1. 子线程中遇到错误怎么排查

题目理解:咨询的是怎么捕获子线程中的异常。

  1. try catch
  2. 设置线程的异常回调接口 thread.setUncaughtExceptionHandler, 当线程运行过程中出现异常时,JVM 会调用 Thread 类的 dispatchUncaughtException 方法,该方法会调用 getUncaughtExceptionHandler().uncaughtException(this,e) 来处理异常。

总结: 如果线程运行中产生了异常,首先会生成一个异常对象。我们平时 throw 抛出异常,就是把异常交给 jvm 处理。jvm 首先会去找有没有能够处理该异常的处理者(首先找到当前抛出异常的调用者,如果当前调用者无法处理,则会沿着方法调用栈一路找下去),能够处理的调用者实际就是看方法的 catch 关键字,jvm 会把该异常对象封装到 catch 入参,允许开发者手动处理异常。若找不到能够处理的处理者(实际就是没有手动 catch 异常,比如未受检异常),就会交该线程处理;JVM 会调用 Thread 类的 dispatchUncaughtException() 方法,该方法调用了 getUncaughtExceptionHandler()uncaughtExceptoin(this,e) 来处理了异常,如果当前线程设置了自己的 UncaughtExceptionHandler, 则使用该 handler, 调用自己的 uncaughtException 方法,如果没有,则使用当前线程所在的线程组的 Handler 的 uncaughtExceptoin() 方法,如果线程中中也没有设置,则直接把异常定向到 System.err 中,打印异常信息(控制台红色字体输出的异常就是被定向到 System.err 的异常)

2. 项目难点

有待整理

3. docker 和虚拟机区别

容器虚拟化的是操作系统而不是硬件,容器之间是共享同一套操作系统资源的。虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统。因此容器的隔离级别会稍低一些。

特性 容器 虚拟机
启动 秒级 分钟级
硬盘使用 一般为 MB 一般为 GB
性能 接近原生 弱于
系统支持量 单机支持上千个容器 一般几十个
  • 容器是一个应用层抽象,用于将代码和依赖资源打包在一起。 多个容器可以在同一台机器上运行,共享操作系统内核,但各自作为独立的进程在用户空间中运行 。与虚拟机相比, 容器占用的空间较少(容器镜像大小通常只有几十兆),瞬间就能完成启动

  • 虚拟机 (VM) 是一个物理硬件层抽象,用于将一台服务器变成多台服务器。 管理程序允许多个 VM 在一台机器上运行。每个 VM 都包含一整套操作系统、一个或多个应用、必要的二进制文件和库资源,因此 占用大量空间 。而且 VM 启动也十分缓慢

  • 虚拟机更擅长于彻底隔离整个运行环境Docker 通常用于隔离不同的应用

4. 容器为什么小?容器缺少所需资源怎么办?

docker 是分层的,

docker基本概念

Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。 镜像不包含任何动态数据,其内容在构建之后也不会被改变。

镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。 比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。

分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。

5. find 命令根据文件内容查文件

find / -name "*.log" | xargs grep "ERROR"

xargs 可以将管道或标准输入(stdin)数据转换成命令行参数,也能够从文件的输出中读取数据。

6. vim 跳转到某行

:n 跳转到 n 行。

gg 第一行

G 末行

7. 快速排序

public void quicksort(int[] nums, int l, int r) {
    if (l < r) {
        int pos = partition(nums, l, r);
        quicksort(nums, l, pos - 1);
        quicksort(nums, pos + 1, r);
    }
}

private int partition(int[] nums, int l, int r) {
    int x = nums[l];
    int k = l - 1; // k 一直指向 <=x 的最后一个下标
    for (int i = l; i <= r; i++) {
        if (nums[i] <= x) {
            swap(nums, ++k, i);
        }
    }
    swap(nums, k, l);
    return k;
}

8.