1.jdk自带线程池?
-
固定大小线程池 (
FixedThreadPool
)Executors.newFixedThreadPool(int nThreads)
- 创建一个固定数量线程的线程池,无论有多少任务提交到线程池,线程池始终维持固定的线程数。超过核心线程数的任务将会进入队列排队等待执行,直到线程池中有线程空闲。
-
可缓存线程池 (
CachedThreadPool
)Executors.newCachedThreadPool()
- 创建一个可灵活调整线程数量的线程池,线程池中如果没有正在运行的线程时,当有任务提交时,会创建新线程来执行任务;线程闲置一段时间后会被回收,以减少系统资源消耗。
-
单线程线程池 (
SingleThreadExecutor
)Executors.newSingleThreadExecutor()
- 创建一个只有一个工作线程的线程池,所有提交的任务都将在这个线程上按照提交顺序进行串行执行,保证任务间的执行顺序。
-
定时/周期性任务线程池 (
ScheduledThreadPoolExecutor
)Executors.newScheduledThreadPool(int corePoolSize)
- 创建一个支持定时及周期性任务执行的线程池,除了常规线程池功能外,还可以调度延迟执行的任务或定期执行的任务。
2.为什么阿里不建议使用?
-
资源耗尽风险:
-
Executors.newFixedThreadPool(int nThreads)
创建的固定大小线程池,虽然可以限制最大线程数,但如果任务队列未做适当配置(如默认情况下使用的是无界队列LinkedBlockingQueue
),在极端情况下,任务提交速度过快,可能导致队列中堆积过多任务,从而占用大量内存,引起内存溢出(OOM)。 -
Executors.newCachedThreadPool()
创建的是可伸缩线程池,理论上线程数量可以无限增长,如果任务执行速度远低于提交速度,可能导致系统资源耗尽,同样产生OOM风险。
-
-
线程池配置不可定制:
- 默认提供的线程池配置不一定能满足所有业务场景,例如拒绝策略、线程存活时间、队列大小等参数通常是硬编码的,不能根据实际情况灵活调整。
-
缺乏合理的任务拒绝处理:
- 当线程池和任务队列饱和时,默认的拒绝策略(AbortPolicy,抛出
RejectedExecutionException
异常)可能不是所有场景下理想的处理方式。
- 当线程池和任务队列饱和时,默认的拒绝策略(AbortPolicy,抛出
-
线程生命周期管理:
- 默认配置可能忽视了对线程生命周期的有效管理,例如空闲线程的回收策略,这在长时间运行的服务中可能会积累大量空闲线程,浪费系统资源。
因此,阿里巴巴提倡直接通过ThreadPoolExecutor
构造函数自定义线程池,这样可以根据实际业务场景细致地调整线程池的各种参数,以达到更好的性能、资源利用率和稳定性。例如,可以选择有界队列,设定合理的拒绝策略,并对线程的最大数目、存活时间等参数进行适当的约束和管理。
3.线程池核心参数有哪些?
-
corePoolSize(核心线程数): 这是线程池的基本大小,即使在没有任务执行时也会一直存在的线程数。当线程池中有任务提交时,如果当前线程数小于核心线程数,线程池会优先创建新的线程来执行任务,而不是放入任务队列。
-
maximumPoolSize(最大线程数): 线程池所能容纳的最大线程数量。如果当前线程数达到核心线程数并且任务队列已满,线程池还会尝试创建新的线程来处理任务,直到线程总数达到最大线程数为止。
-
keepAliveTime(线程空闲存活时间): 当线程池中的线程数量超过核心线程数时,非核心线程在空闲状态下等待新任务到达的最长等待时间。超时后,如果线程池中仍有超过核心线程数的空闲线程,这部分线程将被终止。
-
unit(时间单位): 与
keepAliveTime
搭配使用,用于指定存活时间的具体单位,例如TimeUnit.SECONDS
、TimeUnit.MILLISECONDS
等。 -
workQueue(任务队列): 当线程池中的线程都在忙碌且线程数达到了核心线程数时,新提交的任务将被放入任务队列中等待执行。队列的类型和大小会影响线程池的工作方式,常见的队列有无界队列、有界队列等。
-
threadFactory(线程工厂): 用于创建新线程的工厂,可以用来设置线程的名称、优先级以及其他属性,或为线程池创建线程时插入自定义逻辑。
-
handler(拒绝策略): 当线程池和任务队列均处于饱和状态,即线程数达到最大且任务队列已满时,新提交的任务将触发拒绝策略。常见的拒绝策略有:
AbortPolicy
(默认):直接抛出RejectedExecutionException
异常。CallerRunsPolicy
:调用者所在线程亲自执行被拒绝的任务。DiscardPolicy
:默默地丢弃新提交的任务。DiscardOldestPolicy
:抛弃任务队列中最旧的一个任务,然后尝试把新提交的任务放入队列。
4.项目中有没有用过调度器?
- 在Spring Boot项目中,可以使用Spring的
@Scheduled
注解结合TaskScheduler
或ScheduledExecutorService
实现后台任务调度。
5.sprig自带task与xxl-job区别?
特点:
- Spring Task 是 Spring 框架内建的支持,通过
@Scheduled
注解可以方便地在 Spring 管理的 Bean 中定义定时任务。 - 能够根据 cron 表达式或者其他定时策略来调度方法的执行。
- 适用于简单的定时任务场景,特别是与应用业务逻辑紧密相关的任务。
- 执行任务时,所有的任务逻辑都在同一个应用进程中执行,因此任务调度和执行受单个应用实例的资源限制。
局限:
- 不具备分布式任务调度能力,当需要在多节点间分发任务时,需要借助其他分布式协调服务(如Zookeeper等)自行实现。
- 在大型分布式系统中,无法做到任务的高可用性,单个应用实例挂掉会导致任务中断。
- 资源利用受限于单个应用服务器,难以进行横向扩展。
XXL-Job
特点:
- XXL-Job 是一个分布式任务调度框架,特别针对复杂的分布式任务调度场景设计。
- 提供了可视化的任务调度中心,可以集中管理和监控所有任务执行情况。
- 支持分布式任务调度,任务可以跨多个服务器实例执行,具备高可用性和负载均衡能力。
- 支持任务分片、失败重试、报警通知、权限管理等功能。
- 轻量级设计,易于安装和部署,同时支持丰富的任务类型,包括但不限于定时任务。
对比: 相较于 Spring Task,XXL-Job 更适用于中大型项目或需要处理大量定时任务、任务之间需要协同调度、以及需要高度可靠性和扩展性的场景。Spring Task 更适合小型项目或是不需要分布式调度需求的情况。
简而言之,Spring Task 是轻量级的内置解决方案,适合简单的定时任务需求,而 XXL-Job 则是一个完备的分布式任务调度平台,适合复杂的企业级应用。
6.mongoDB与Mysql区别?优势?
-
数据模型:
- MySQL 是关系型数据库(RDBMS),采用表格结构存储数据,遵循 ACID(原子性、一致性、隔离性、持久性)原则,数据以行和列的形式组织,强制实施数据的一致性和完整性。
- MongoDB 是非关系型数据库(NoSQL),属于文档型数据库,数据以 JSON-like 文档(BSON)的形式存储,每个文档可以有不同的键值对结构,更灵活,支持嵌套结构和数组。
-
查询语言:
- MySQL 使用 SQL(Structured Query Language)进行数据查询、更新和管理。
- MongoDB 使用 MQL(MongoDB Query Language),这是一种基于 JSON 的查询方式,支持丰富的查询条件和聚合操作。
-
数据存储和查询效率:
- MySQL 在结构化数据、复杂联接查询、数据一致性要求高的场景表现优秀,通过索引优化查询速度。
- MongoDB 对于半结构化和非结构化数据存储友好,查询速度快,尤其在读写密集型应用和快速读取大量数据的场景中表现出色,因为它将热数据存储在内存中,适合处理海量数据。
优势:
MySQL 的优势:
- 成熟稳定,有广泛的社区支持和丰富的周边生态。
- 严格的数据一致性,适合需要强一致性的金融、事务型应用。
- SQL 查询语言标准化,学习成本低,SQL 引擎优化成熟。
- 对于复杂的关系查询有成熟的解决方案。
MongoDB 的优势:
- 动态灵活的数据模型,容易适应不断变化的应用需求。
- 高性能读写,尤其在读多写少或频繁增删改查的场景下。
- 优秀的水平扩展能力,能够轻松应对大数据量和高并发访问。
- 内置高可用和容灾机制,如副本集(Replica Set)提供冗余和故障转移功能。
- 对于现代 web 和移动应用中常见的非结构化数据和 JSON 数据有很好的原生支持。
7.mogoDB在哪些场景使用?
-
网站数据存储:
-
游戏开发:
-
物流与电商:
-
社交网络:
-
物联网(IoT):
-
日志记录与分析:
-
内容管理系统:
-
视频直播和流媒体:
-
缓存系统:
-
大数据分析:
8.ES是什么?分词器?
Elasticsearch 是一个基于 Apache Lucene 构建的开源分布式搜索引擎和分析引擎。它专为云计算环境设计,提供了一个分布式的、高可用的实时分析和搜索平台。Elasticsearch 可以处理大量数据,并且具备横向扩展能力,能够通过增加更多的硬件资源来应对数据和查询量的增长。
9.ES的使用场景?
-
全文搜索:
-
日志分析与监控:
-
数据分析:
-
NoSQL JSON文档数据库:
-
搜索推荐:
-
地理信息系统:
-
大规模监控系统:
10.你们项目的日志如何处理?
11.什么是MDC?原理?
是 log4j 和 logback 提供的一种方便在多线程条件下记录日志的功能。
原理:
- MDC的工作原理是利用线程绑定数据的技术,即每个线程都有独立的MDC上下文,线程之间互不影响。在处理请求的线程中,开发者可以通过MDC API将相关信息放入MDC的Map中,然后在配置好的Layout(布局器)中,可以通过占位符等方式引用MDC中的内容,这样在输出日志时,日志框架会自动从当前线程的MDC中取出对应信息加入到日志消息中。
- 在多线程环境下,如Servlet容器中的每个HTTP请求都会创建一个新的线程来处理,MDC的值会在请求开始时设置,并在请求结束时清除,确保了请求间不会互相干扰,同时也使得日志可以准确地关联到具体的请求上下文中。