- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
最近有位小伙伴在我的技术群里,问了我一个问题:服务down机了,线程池中如何保证不丢失数据?
这个问题挺有意思的,今天通过这篇文章,拿出来跟大家一起探讨一下.
之前没有线程池的时候,我们在代码中,创建一个线程有两种方式:
虽说通过这两种方式创建一个线程,非常方便.
但也带来了下面的问题:
为了解决上面的这些问题,Java中引入了:线程池.
它相当于一个存放线程的池子.
使用线程池带来了下面3个好处:
先看看线程池的构造器:
public ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
线程池的核心流程图如下:
线程池的工作过程如下:
说白了在线程池中,多余的任务会被放到workQueue任务队列中.
这个任务队列的数据保存在内存中.
这样就会出现一些问题.
接下来,看看线程池有哪些问题.
在JDK中为了方便大家创建线程池,专门提供了Executors这个工具类.
Executors.newFixedThreadPool,它可以创建固定线程数量的线程池,任务队列使用的是LinkedBlockingQueue,默认最大容量是Integer.MAX_VALUE.
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
return new ThreadPoolExecutor(nThreads,
nThreads,
0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory);
}
如果向newFixedThreadPool线程池中提交的任务太多,可能会导致LinkedBlockingQueue非常大,从而出现OOM问题.
Executors.newCachedThreadPool,它可以创建可缓冲的线程池,最大线程数量是Integer.MAX_VALUE,任务队列使用的是SynchronousQueue.
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0,
Integer.MAX_VALUE,
60L,
TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
如果向newCachedThreadPool线程池中提交的任务太多,可能会导致创建大量的线程,也会出现OOM问题.
如果线程池在执行过程中,服务突然被重启了,可能会导致线程池中的数据丢失.
上面的OOM问题,我们在日常开发中,可以通过自定义线程池的方式解决.
比如创建这样的线程池:
new ThreadPoolExecutor(8,
10,
30L,
TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(300),
threadFactory);
自定义了一个最大线程数量和任务队列都在可控范围内线程池.
这样做基本上不会出现OOM问题.
但线程池的数据丢失问题,光靠自身的功能很难解决.
线程池中的数据,是保存到内存中的,一旦遇到服务器重启了,数据就会丢失.
之前的系统流程是这样的:
用户请求过来之后,先处理业务逻辑1,它是系统的核心功能.
然后再将任务提交到线程池,由它处理业务逻辑2,它是系统的非核心功能.
但如果线程池在处理的过程中,服务down机了,此时,业务逻辑2的数据就会丢失.
那么,如何保证数据不丢失呢?
答:需要提前做持久化.
我们优化的系统流程如下:
用户请求过来之后,先处理业务逻辑1,紧接着向DB中写入一条任务数据,状态是:待执行.
处理业务逻辑1和向DB写任务数据,可以在同一个事务中,方便出现异常时回滚.
然后有一个专门的定时任务,每个一段时间,按添加时间升序,分页查询状态是待执行的任务.
最早的任务,最先被查出来.
然后将查出的任务提交到线程池中,由它处理业务逻辑2.
处理成功之后,修改任务的待执行状态为:已执行.
需要注意的是:业务逻辑2的处理过程,要做幂等性设计,同一个请求允许被执行多次,其结果不会有影响.
如果此时,线程池在处理的过程中,服务down机了,业务逻辑2的数据会丢失.
但此时DB中保存了任务的数据,并且丢失那些任务的状态还是:待执行.
在下一次定时任务周期开始执行时,又会将那些任务数据重新查询出来,重新提交到线程池中.
业务逻辑2丢失的数据,又自动回来了.
如果要考虑失败的情况,还需要在任务表中增加一个失败次数字段.
在定时任务的线程池中执行业务逻辑2失败了,在下定时任务执行时可以自动重试.
但不可能无限制的一直重试下去.
当失败超过了一定的次数,可以将任务状态改成:失败.
这样后续可以人工处理.
。
最后说一句(求关注,别白嫖我) 如果这篇文章对您有所帮助,或者有所启发的话,帮忙扫描下发二维码关注一下,您的支持是我坚持写作最大的动力.
求一键三连:点赞、转发、在看。 关注公众号:【苏三说技术】,在公众号中回复:面试、代码神器、开发手册、时间管理有超赞的粉丝福利,另外回复:加群,可以跟很多BAT大厂的前辈交流和学习.
最后此篇关于服务重启了,如何保证线程池中的数据不丢失?的文章就讲到这里了,如果你想了解更多关于服务重启了,如何保证线程池中的数据不丢失?的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我在 Ubuntu 10.04 LTS 上运行 Eclipse Galileo。今天 Ubuntu 在我身上崩溃了,重新启动后,我发现 Eclipse 已经完全失去了 Java Perspective
我使用配置了 sonata_user 的 SonataAdminBundle在 config.yml : sonata_user: impersonating: route:
我有 ubuntu 14.04 但它不见了 docker exec sudo docker exec -it ubuntu_bash bash 我希望在现有正在运行的 docker 容器中运行交互式
我正在使用 Ubuntu 8.04/32 位(作为虚拟机)。在一个不是 min 的项目上执行一些 make 时,我得到了错误: g++:/usr/lib/libstdc++.a: 没有这样的文件或目录
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许在 Stack Overflow 上提出有关通用计算硬件和软件的问题。您可以编辑问题,使其成为
我正在尝试获取有关我在 UIImagePicker 中选择的视频的一些数据。 因此,当它进入 UIImagePicker 委托(delegate)方法(如下)时,我知道我需要使用信息字典中的 UIIm
我的网站最近被可能的黑客行为删除了。我上传了备份的文件夹和数据库,但现在我的 View 没有显示。其他一切都有效。我想不出有什么变化,只是上传了几天前的备份。 这些字段在 admin/build/vi
我执行以下操作来设置我的 session ,这是有效的,因为 echo 出现了。但是当我转到下一页或另一页时, session 不存在吗?我做错了什么? $session_start(); if ($
我试图在 BigQuery 中使用这段代码,显然是从 GA 中获取数据,但 _TABLE_SUFFIX 似乎有问题。错误显示“错误:无法识别的名称:_TABLE_SUFFIX at [12:3]”您能
输入:8(2 5 6 9 10 2 7 4)预期输出:(2 7 9 9 12 5 7 6)实际输出:(2 7 9 9) 这是我的大学作业,也是我第一次在这里提问。我不知道为什么,但 10 没有扫描,有
$('div'); // 我在上面的代码中遇到错误。在检查 .js 代码时,我找不到名为 $ 的函数,但根据文档,应该有一个。 最佳答案 试试 http://ajax.googleapis.co
以下简单代码的输出对我来说有点奇怪。它错过了在控制台上打印的 0 到 100 之间的一些数字。 谁能解释一下为什么省略打印?我对并发编程完全陌生。 import java.util.concurren
我正在学习 xamarin 以构建移动应用程序,但我对 Xamarin 和移动应用程序一无所知。我打开了一个空白的移动应用程序,其中有“Hello world”示例并编辑了一些文本,但我的应用程序图标
我正在将一些值存储到 sqlite 数据库中。因此,数据是作为字符串从文本字段收集的,然后转换为 double 并持久化。 这是我试过的 NSDecimalNumber 答案; value.answe
我有一个奇怪的案例。突然,其中一个表中的一些记录(这么多记录)丢失了。首先,我认为这是由我的 PHP 脚本中的错误引起的。但是,我检查了一下,我的脚本中没有DELETE操作,只有UPDATE。有谁知道
我正在复制 NSString来自 NSDictionary进入本地NSString使用 [[NSString alloc] initWithString:] ,对其进行处理(删除一些字符),然后将其发
当保存在根文件夹中时,我的非常基本的 html 页面保持样式。为一个组创建了一个新文件夹,但是当我将页面移动到该文件夹时,它们似乎失去了与 css 文件的连接。 认为问题可能出在链接上,因为它现在
我需要使用 OpenCV 训练一些图像。但问题是,我找不到 opencv_createsamples 程序。我以正常方式安装了 OpenCV,因为我使用的是 Windows 7。这个 opencv_c
我有一个绑定(bind)到 JTable 的 ArrayList。之后 bindingGroup.unbind(); bindingGroup.bind(); (完成刷新数据)我丢失了表格单元格渲
所以基本上我们只是丢失了一个 keystore 和备份 keystore 。但是我们可能知道原始 keystore 的密码。 我的问题是,如果我们知道原始 keystore 的密码,我们可以重新生成
我是一名优秀的程序员,十分优秀!