面试官:第一轮提问开始。首先,讲讲Java中的多线程有哪些实现方式?
王铁牛:多线程实现方式有继承Thread类、实现Runnable接口,还有实现Callable接口通过FutureTask包装来获取结果。
面试官:回答得不错。那线程池的核心参数有哪些?
王铁牛:核心参数有corePoolSize(核心线程数)、maximumPoolSize(最大线程数)、keepAliveTime(线程存活时间)、unit(时间单位)、workQueue(任务队列)、threadFactory(线程工厂)、handler(拒绝策略)。
面试官:很好。再问个问题,HashMap在多线程环境下会出现什么问题?
王铁牛:会出现死循环、数据丢失等问题,因为它不是线程安全的。
面试官:第一轮结束。接下来第二轮提问。说说Spring的核心特性有哪些?
王铁牛:Spring的核心特性有依赖注入、面向切面编程、IoC容器等。
面试官:那Spring Boot的自动配置原理是什么?
王铁牛:Spring Boot通过@EnableAutoConfiguration注解开启自动配置,它会根据类路径下的依赖自动配置相关的Bean。
面试官:不太清晰。MyBatis的缓存机制了解吗?
王铁牛:有一级缓存和二级缓存,一级缓存是SqlSession级别的,二级缓存是Mapper级别的。
面试官:第二轮结束。进入第三轮提问。Dubbo的集群容错策略有哪些?
王铁牛:有Failover Cluster(失败自动切换)、Failfast Cluster(快速失败)、Failsafe Cluster(失败安全)等。
面试官:RabbitMq的消息确认机制是怎样的?
王铁牛:有生产者确认和消费者确认,生产者确认又分事务确认和publisher confirm。
面试官:xxl-job的调度中心是如何实现任务调度的?
王铁牛:不太清楚。
面试官:面试结束,回家等通知吧。
答案:
- 多线程实现方式:
- 继承Thread类:创建一个类继承Thread类,重写run方法,通过创建该类的实例并调用start方法来启动线程。
- 实现Runnable接口:创建一个类实现Runnable接口,实现run方法,然后将该类实例作为参数传入Thread类的构造函数创建线程对象并启动。
- 实现Callable接口:创建一个类实现Callable接口,实现call方法,通过FutureTask包装该类实例,再将FutureTask传入Thread类构造函数创建线程对象并启动,通过FutureTask的get方法获取线程执行结果。
- 线程池核心参数:
- corePoolSize:核心线程数,当提交的任务数小于corePoolSize时,会创建新线程执行任务。
- maximumPoolSize:最大线程数,当提交任务数大于corePoolSize且任务队列已满时,会创建线程直到线程数达到maximumPoolSize。
- keepAliveTime:线程存活时间,当线程数大于corePoolSize且线程空闲时间超过keepAliveTime时,多余线程会被销毁。
- unit:时间单位,指定keepAliveTime的时间单位。
- workQueue:任务队列,用于存放提交的任务。
- threadFactory:线程工厂,用于创建线程,可自定义线程的名称、优先级等。
- handler:拒绝策略,当线程数达到maximumPoolSize且任务队列已满时,会调用handler处理新提交的任务。
- HashMap多线程问题:
- 死循环:在扩容时可能会形成环形链表,导致后续get操作可能陷入死循环。
- 数据丢失:在并发写操作时,如果同时进行扩容和写操作,可能会导致数据覆盖或丢失。
- Spring核心特性:
- 依赖注入:通过IoC容器将对象之间的依赖关系进行管理和注入。
- 面向切面编程:通过切面来实现横切关注点,如日志、事务等。
- IoC容器:负责创建、管理和装配Bean。
- Spring Boot自动配置原理:
- @EnableAutoConfiguration注解:开启自动配置功能,它会根据类路径下的依赖查找对应的自动配置类。
- 自动配置类:根据依赖条件自动配置相关的Bean,如数据源、事务管理器等。
- MyBatis缓存机制:
- 一级缓存:是SqlSession级别的缓存,在同一个SqlSession中执行相同的查询,会直接从缓存中获取结果,避免重复查询数据库。
- 二级缓存:是Mapper级别的缓存,多个SqlSession可以共享二级缓存,通过在Mapper.xml中配置标签来开启。
- Dubbo集群容错策略:
- Failover Cluster:失败自动切换,当调用失败后会自动重试其他服务。
- Failfast Cluster:快速失败,当调用失败立即返回错误,不进行重试。
- Failsafe Cluster:失败安全,当调用失败时不抛出异常,直接忽略。
- RabbitMq消息确认机制:
- 生产者确认:
- 事务确认:通过channel.txSelect开启事务,然后进行消息发送,最后通过channel.txCommit提交事务,如果发送失败会回滚事务。
- publisher confirm:通过channel.confirmSelect开启确认模式,消息发送后通过addConfirmListener监听确认结果。
- 消费者确认:消费者接收到消息后,通过basicAck方法手动确认消息已接收。
- 生产者确认:
- xxl-job调度中心实现任务调度:
- 调度中心基于数据库和定时任务框架来实现任务调度。它会将任务信息存储在数据库中,通过定时任务框架按照设定的时间间隔或触发条件来读取任务并执行。调度中心会根据任务的配置信息,如执行时间、执行频率等,计算出任务的执行时间点,并将任务分发给相应的执行器去执行。同时,调度中心还会对任务的执行结果进行监控和记录,以便后续查看和处理。