服务重启了,如何保证线程池中的数据不丢失?
创作时间:
作者:
@小白创作中心
服务重启了,如何保证线程池中的数据不丢失?
引用
1
来源
1.
https://www.cnblogs.com/12lisu/p/18388411
在Java开发中,线程池是提高程序性能和资源利用率的重要工具。但是,当服务意外重启时,线程池中的数据可能会丢失,这给系统的稳定性和可靠性带来了挑战。本文将深入探讨线程池的工作原理,并提出一种通过数据持久化来避免数据丢失的解决方案。
什么是线程池?
在Java中,线程池是一种用于管理和复用线程的机制。它通过维护一个线程集合来处理任务,从而避免了频繁创建和销毁线程带来的性能开销。线程池的主要优点包括:
- 降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
- 提高响应速度:当任务到达时,可以直接使用已有空闲的线程,不需要的等到线程创建就能立即执行。
- 提高线程的可管理性:线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性。而如果我们使用线程池,可以对线程进行统一的分配、管理和监控。
线程池的构造器如下:
public ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
corePoolSize:核心线程数,线程池维护的最少线程数。maximumPoolSize:最大线程数,线程池允许创建的最大线程数。keepAliveTime:线程存活时间,当线程数超过核心线程数时,多余的空闲线程的存活时间。unit:时间单位。workQueue:任务队列,用于保存等待执行的任务。threadFactory:线程工厂,用于创建新线程。handler:拒绝策略,当任务无法执行时的处理策略。
线程池的工作流程如下:
- 线程池初始化:根据
corePoolSize初始化核心线程。 - 任务提交:当任务提交到线程池时,根据当前线程数判断:
- 若当前线程数小于
corePoolSize,创建新的线程执行任务。 - 若当前线程数大于或等于
corePoolSize,任务被加入workQueue队列。
- 任务处理:当有空闲线程时,从
workQueue中取出任务执行。 - 线程扩展:若队列已满且当前线程数小于
maximumPoolSize,创建新的线程处理任务。 - 线程回收:当线程空闲时间超过
keepAliveTime,多余的线程会被回收,直到线程数不超过corePoolSize。 - 拒绝策略:若队列已满且当前线程数达到
maximumPoolSize,则根据拒绝策略处理新任务。
线程池存在的问题
虽然线程池带来了诸多好处,但在实际使用中也存在一些问题:
3.1 队列过大
Executors.newFixedThreadPool创建的线程池使用LinkedBlockingQueue作为任务队列,默认最大容量是Integer.MAX_VALUE。如果向此类线程池中提交的任务太多,可能会导致队列非常大,从而出现OOM问题。
3.2 线程太多
Executors.newCachedThreadPool创建的线程池最大线程数量是Integer.MAX_VALUE,任务队列使用的是SynchronousQueue。如果向此类线程池中提交的任务太多,可能会导致创建大量的线程,也会出现OOM问题。
3.3 数据丢失
如果线程池在执行过程中,服务突然被重启了,可能会导致线程池中的数据丢失。这个问题在实际生产环境中尤为关键,需要特别注意。
如何保证数据不丢失?
线程池中的数据保存在内存中,一旦遇到服务器重启,数据就会丢失。为了解决这个问题,可以采用以下方案:
- 用户请求过来之后,先处理业务逻辑1,紧接着向DB中写入一条任务数据,状态是:待执行。
- 处理业务逻辑1和向DB写任务数据,可以在同一个事务中,方便出现异常时回滚。
- 有一个专门的定时任务,每个一段时间,按添加时间升序,分页查询状态是待执行的任务。
- 最早的任务,最先被查出来。
- 然后将查出的任务提交到线程池中,由它处理业务逻辑2。
- 处理成功之后,修改任务的待执行状态为:已执行。
- 需要注意的是:业务逻辑2的处理过程,要做幂等性设计,同一个请求允许被执行多次,其结果不会有影响。
- 如果此时,线程池在处理的过程中,服务down机了,业务逻辑2的数据会丢失。
- 但此时DB中保存了任务的数据,并且丢失那些任务的状态还是:待执行。
- 在下一次定时任务周期开始执行时,又会将那些任务数据重新查询出来,重新提交到线程池中。
- 业务逻辑2丢失的数据,又自动回来了。
- 如果要考虑失败的情况,还需要在任务表中增加一个失败次数字段。
- 在定时任务的线程池中执行业务逻辑2失败了,在下定时任务执行时可以自动重试。
- 但不可能无限制的一直重试下去。
- 当失败超过了一定的次数,可以将任务状态改成:失败。
- 这样后续可以人工处理。
通过这种提前持久化数据的方式,即使服务重启,也不会导致数据丢失,同时通过定时任务和幂等性设计,可以确保任务的可靠执行。
热门推荐
电路板还有软硬之分?刚性PCB和柔性FPC到底有什么不同?
玩小游戏真的能赚钱吗?四种变现方式详解
带间隙磁芯电感器的工作原理与优势
未来之盾 未来而行 为爱而生——青春志愿服务传递温暖与力量
探索汉字“枭”的读音与文化内涵,追寻卓越与成功的精神之旅
如何进行合理的股票和国债投资组合?股票国债购买的策略有哪些实际应用?
电脑文档怎么共享?最全的分享攻略教你轻松实现文件共享
冬天进补,来一锅牛肉炖萝卜,小火慢炖滋味浓,全家人都爱吃
正交性在线性代数中的重要性及应用
机器学习中加正交约束避免平凡解怎么理解呢
生存和繁衍对于人类的重要性是什么?
住房公积金结息了!快查查您收到多少
Open3D 点云的ISS关键点提取
世界肝炎日|感染乙肝终身无法“摘帽”?真实案例分享:临床治愈不是梦
劳动合同工资低于当地最低工资有效吗
汉语言文学专业职业发展路径规划与探索
带娃坐飞机不再慌!这份超全攻略请收好
合同盖章的效力有哪些规定
雷电4和USB4接口标准大对比:性能、兼容性与应用场景全解析
维生素C是蓝莓的4倍,被誉为“21世纪最佳保健水果”,现在吃正好
33W快充揭秘:你的手机多久能满血复活?
手机提前报废,只因没分清 “快充”和“闪充” ?
什么是预测分析(Predictive Analytics)?
你了解自己的肺功能吗?自评和居家锻炼实用方法来了!
健康从硒开始:四大类含硒食物,轻松搞懂硒如何改变你的健康状况
【完整指南】掌上压(俯卧撑)完全教学:从入门到进阶
宁波忻氏家族:六百年来传承“尚义”家风
如何理解IGCSE物理中的电流概念
摄影技艺全揭秘:设备、光线与构图,助你摄影技艺大飞跃!
如何通过社交媒体和内容营销提升网站知名度?