multithreading - 在请求之间共享应用程序线程池
问题描述
我有一个基于 Spring 的应用程序,它带有一个 REST 服务,它导入一个 CSV 文件,解析它的内容,并在一些记录处理之后将数据(再次记录)存储到数据库中。将数据存储到数据库非常耗时,因为文件可以增长到数千条记录。
现在我想到了多线程 - 将处理和存储到数据库的数据委托给线程。我认为这是个好主意,但后来我想通了:等待 - 可能有多个用户同时导入文件,因此创建每个请求具有数百个线程池的线程池可能不是一个好主意。
是否可以为每个应用程序创建一个包含 1000 个线程的线程池,并在到达应用程序的所有请求之间共享这个线程池 - 是的。但是我如何限制每个线程占用的线程数?
我想限制每个应用程序的线程数以不使服务器超载,并且我想限制每个请求所占用的线程数,以使没有一个线程消耗所有可用资源(特别是在这种情况下的线程)并饿死所有其他资源可能会出现的请求...
有什么想法、想法吗?
解决方案
重新表述你的问题
这是一个相当复杂的情况。我将尝试改写它,看看我是否正确理解了您想要的行为。
您有几个应用程序可能会接收要在中央数据库上进行的批量更新。这些更新分批来自 CSV 文件,每批可以包含数千条记录。您希望并行处理这些更新,但是:
- 您想限制每个应用程序使用的线程数
- 如果并行处理多个批次,您希望保证单个批次的进度
第一个有缺陷的提案
要限制每个应用程序使用的线程数,您可以为每个应用程序使用固定大小的执行器服务。通过为每个 ExecutorService 的底层线程池赋予适当的大小,可以保证单个应用程序不会饿死其他应用程序。
然后可以将单个记录作为单个任务提交给执行器服务。如果单个应用程序正在处理多个批次,则来自这些批次的各个记录将被放入 Executor 服务中的单个队列中。来自不同批次的记录将交错,因为它们混合在执行器服务的单个队列中。
这个解决方案的问题是它不能保证所有批次都同时处理。假设您有一个包含 4 个线程的池来支持执行程序服务。如果有大批量的记录提交给执行器服务,所有 4 个线程都会开始处理这些记录。现在,如果第二批进来,它将在第一批之后加入队列,这意味着 4 个线程将在处理第二批之前处理第一批的所有记录。这很好,因为 4 个线程一直保持忙碌,但这不是您想要的行为。在这种情况下,您希望池中至少有一个线程开始处理第二批的记录,对吗?
一个可能的解决方案?
我认为您可以实现类似于适合您特定问题的 Fixed Thread Executor 服务的东西。这就是我要做的。
您可以创建一个线程池(以下称为“工作线程”)来处理来自多个队列的单个记录。一个队列对应一批记录。当需要处理一个新批次时,创建一个新队列并将其插入队列环中,工作线程从中获取记录以进行处理。将您的记录放入其中,以便线程可以在另一端处理它们,并在您的批处理完成时从环中删除队列(队列为空,您没有更多记录可放入此批处理)。所有队列都保持在一个环中,以便每个线程都可以遵循以下例程:
- 处理队列中的记录
- 移动到下一个队列(比如说右边的队列)
- 从第 1 步开始重复
使用这样的方案,您可以确保无论有多少批次来来去去,它们都会取得进展,即使批次多于需要处理它们的线程。如果当前只有一个正在处理,工作线程也将能够专注于单个批次。
我建议您使用ConcurrentLinkedQueue 之类的东西来管理您的批次。显然,在实现这种机制时存在许多编程陷阱。
- 当队列从环中移除时,工作线程对队列的并发访问,
- 当没有队列并且没有要处理的记录时如何处理工作线程),
- 当工作人员检查队列中的记录但没有要处理的记录时你会怎么做(跳到下一个队列?)
- 当只有一个队列但所有记录都已处理完毕并且工作人员正在挨饿时(阻塞地等待队列等待记录到来?如果批处理实际上完成了怎么办)
鉴于您的问题的复杂性,您似乎很有经验,我认为您应该能够弄清楚这一点。如果不是,我希望在 StackOverflow 上看到您提出的更多问题!
推荐阅读
- angular-reactive-forms - 初始化后如何在Angular 4中将值设置为FormArray?
- javascript - AngularJs 1.x 项目从 Gulp/Grunt 迁移到 Webpack
- ruby - 如何解释这些 ruby 代码的性能差异?
- ios - UITableViewCell Layer Shadow Overlap Cell 上面
- c# - 服务器错误 i / 应用程序
- node.js - 不能安排 aws-sns 吗?
- ruby-on-rails - 迁移中的模型验证 - Ruby on Rails
- windows - Wix 引导程序多个超链接文本
- java - 总是出现运行时错误#Java
- unity3d - 在批处理模式下运行Unity时无法使用Build Target ios