服务重启了,如何保证线程池中的数据不丢失?
创作时间:
作者:
@小白创作中心
服务重启了,如何保证线程池中的数据不丢失?
引用
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失败了,在下定时任务执行时可以自动重试。
- 但不可能无限制的一直重试下去。
- 当失败超过了一定的次数,可以将任务状态改成:失败。
- 这样后续可以人工处理。
通过这种提前持久化数据的方式,即使服务重启,也不会导致数据丢失,同时通过定时任务和幂等性设计,可以确保任务的可靠执行。
热门推荐
深圳跨境电商为啥火爆?
新手养大型犬的最佳选择(如何选择适合自己的大型犬,打造和谐的宠物生活)
适合学生党养的狗狗(容易照顾、不耽误学习的理想宠物选择)
徐福东渡日本的传奇与影响
经常在睡前玩手机,用不了多久,或会摊上这5个“毛病”
双语语料库挖掘与翻译辅助
【实用】牛奶怎么选?教你看配料表和营养成分表!
如何治疗海绵体毛细血管瘤
抗战时期,民国海军在干什么?
秦朝饮食文化:探索古代主食的多样性
从育种到餐桌:贵州三穗鸭产业年产值破10亿元
黄龙景区游览路线攻略
抽动症该如何进行营养干预
帮信罪能申请免费律师吗
自媒体运营插图图片,自媒体运营中,如何有效利用插图图片提升内容吸引力?
拿20万去银行存款,如果存钱的方式没选对,利息要少一大半
快递的"私密发货"真的保密吗?你买了什么东西有谁会知道呢?
刚想做的事情,怎么转头就忘了!到底是为什么?
迁户口带什么材料:详细清单及法律依据
成都6天旅游攻略:从历史文化到自然风光的完美行程规划
如何了解设计师的收费标准?合理的收费标准应该如何制定?
装修设计师收费标准及资格详解
400度近视眼角膜偏薄应如何处理
氨气对人体有哪些危害?解析氨气对健康的影响
‘脾胃是后天之本,什么是先天之本’是什么意思?
睡眠要看什么科室
速看!10个常见电脑问题解决方案全在这儿
进社区、进楼宇、进商圈,大宁路街道文化遗产季系列活动开展
二手车ETC办理指南:不同情况下的具体操作流程
手支撑体式中手腕疼怎么办