SummerXinBing / xiabing_wuji

学习仓库,用此来驱动自己
Apache License 2.0
0 stars 0 forks source link

Shine 面试 #24

Open SummerXinBing opened 1 month ago

SummerXinBing commented 1 month ago

1.项目亮点难点处理方案,java服务容器中除了堆内堆外还有哪些内存占用 2.线程池工作原理 3.线程池线程数量设置依据 4.线程池中某个线程执行报异常了,该线程会怎么样,怎样在主线程中获取该异常 5.ThreadLocal原理、ThreadLocalMap原理、什么情况下会出现内存泄露、什么情况下会出现OOM 6.三个线程,A、B线程同时运行,要求A、B中任意线程执行完毕后C线程继续执行,有哪些实现方案 7.AQS原理,线程入队细节 8.spring中注册 bean的方式有哪些 9.nacos配置动态更新原理、nacos注册中心AP/ CP原理 10.mysql主键索引与唯一索引功能上的区别 11.mysql mvcc原理

SummerXinBing commented 3 weeks ago

线程池的工作原理

  1. 线程池的数量设置依据 a. cpu密集型的任务 比如模型训练等任务,完全使用cpu资源的任务,如果单核cpu开开启多线程反而增加线程切换的开销; 针对cpu密集型的任务,如果和多核cpu,那么核心线程数=cpu核数 b. io密集型的任务: io密集型任务是需要io线程的开销,cpu使用占比越小,就需要越多的线程;那么核心线程数=cpu核数/(1-阻塞系数),阻塞系数一般为0.8-0.9之间;

最大线程数怎么设置?

  1. 线程中池中某个线程异常了,会怎么样?怎么在主线程中获取异常? 任务是需要有返回值,catch一下,该线程结束; 任务是没有返回返回值,catch一下,该线程结束; 主线程是会补货单线程的异常

6.三个线程,A、B线程同时运行,要求A、B中任意线程执行完毕后C线程继续执行,有哪些实现方案 ComplateFutrun 创建异步对象 计算完成时回调 线程串行化 两个任务组合,两个都要完成 两个任务组合,完成一个1

8.spring中注册 bean的方式有哪些 xml 代码 注解

SummerXinBing commented 3 weeks ago

Bean

spring中注册 bean的方式有哪些?

注解扫描 通过打上一些注解@Service @Component @Bean等方式 @Component是 手动配置

Ioc

想到bean,其实就要想到IOC容器,ioc的设计初衷就是提供bean的注册,和bean的定义

BeanFactory

描述:Ioc容器的功能规范 功能:该接口提供一些基础的抽象方法,比如通过Bean的name获取Bean的实例,还有Bean类型等;该接口有3个子类(接口),比如AutowireCapableBeanFactory定义了将IOC容器的Bean按照某种规则(名字、类型)自动装配的方法;

BeanRegistry

描述:Bean的注册

BeanDefinition

描述:描述了各种Bean对象和它们之间的相互关系(Bean有相互循环依赖的问题),抓住3个要点去理解BeanDefinition a BeanDefinition 定义Bean对象和其相互关系 b BeanDefinitionReader BeanDefinition的解析器 Bean的解析过程比较复杂,主要针对Spring的配置文件进行解析,所以需要更多的扩展类去处理; c BeanDefinitionHolder 这是BeanDefination的包装类,用来存储BeanDefinition,name以及aliases等。

问1:怎么解决循环依赖的问题,通过3级缓存;

ApplicationContext

描述:Ioc容器的设计和实现

Bean的实例化 Bean的生命周期和循环依赖

Spring怎么解决单例Bean的循环依赖

一级缓存:单例对象缓存池,已经实例化了,且已经赋值了的成品单例Bean; 二级缓存:单例对象缓存池,已经实例化了但是还没赋值的半成品单例Bean; 三级缓存:单例工厂缓存

private final Map<String, Object> singletonObjects = new CurrentHashMap<String, Object>(256);
private final Map<String, Object> earlyStringObjects = new HashMap<String, Object>(16);
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);

protected Object getBean(String beanName, boolean allowEarlyReference) {
    // Spring尝试去一级缓存中获取
    Object singletonObject = this.singletonObjects.get(beanName);
    // 一级缓存取不到,并且对象正在建立中
    if (singletonObjects == null && isSingletonCurrentlyInCreation(beanName))) {
        // 去二级缓存中
        synchronized(this.earlyStringObjects) {
            Object singletonObject = this.earlyStringObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();

                }
            }
        }
    }
    return singletonObject;
}

上述代码只是描述如何从三级缓存中获取Bean,下面就是如何去模拟解决循环依赖的场景。 对象A依赖对B,对象B依赖对象A;当加载A的时候,在创建A的实例时会先放到BeanFcatort中,提前暴露给其他对象使用的,当创建A的过程中,发现需要创建B,那就去创建B,在创建B的过程中,发现需要依赖A,那就先从缓存中获取对象;

好比“A对象setter依赖B对象,B对象setter依赖A对象”,A首先完成了初始化的第一步,而且将本身提早曝光到singletonFactories中,此时进行初始化的第二步,发现本身依赖对象B,此时就尝试去get(B),发现B尚未被create,因此走create流程,B在初始化第一步的时候发现本身依赖了对象A,因而尝试get(A),尝试一级缓存singletonObjects(确定没有,由于A还没初始化彻底),尝试二级缓存earlySingletonObjects(也没有),尝试三级缓存singletonFactories,因为A经过ObjectFactory将本身提早曝光了,因此B可以经过ObjectFactory.getObject拿到A对象(半成品),B拿到A对象后顺利完成了初始化阶段一、二、三,彻底初始化以后将本身放入到一级缓存singletonObjects中。此时返回A中,A此时能拿到B的对象顺利完成本身的初始化阶段二、三,最终A也完成了初始化,进去了一级缓存singletonObjects中,并且更加幸运的是,因为B拿到了A的对象引用,因此B如今hold住的A对象完成了初始化。

Bean的作用域 单例 原型 请求request 会话session 全局作用域

类加载机制

类加载的过程 加载 、连接(验证、准备、解析)、初始化、使用、卸载;

加载有多种方式,网络加载、本地加载ets。加载就是将二进制流加载到jvm内存中; 验证:验证被加载类的正确性 准备:为类的静态变量分配内存,并初始化值 解析:把类的符号引用转化为直接引用 初始化:为类的成员变量分类内存,并初始化值 使用:jvm在方法去提供了一个接口,用来访问heap中的数据; 卸载:结束生命周期

类加载器的层次 启动类加载器:加载启动类相关,jdk/jre/lib 扩展类加载器:加载扩展类 jdk/jre/lib/ext 应用程序类加载器:加载用户路径java代码 自定义类加载器

类加载机制 全盘委托 父亲机制 双亲委派机制:如果jvm收到了一个类的加载请求,类加载器不会立即去加载,而是去父层加载器寻找(扩展类加载器、启动类加载器),找到就返回;如果找不到,依次往上找,找不到就下一层的类加载器去加载;