Java ScheduledThreadPoolExecutor线程安全

Java ScheduledThreadPoolExecutor线程安全,java,multithreading,Java,Multithreading,ThreadPoolExecutor和ScheduledThreadPoolExecutor是否线程安全?? 现在,我有一个场景如下: 5ThreadPoolExecutor(s) exec1(执行JobA(A级作业):最多4-5个作业的并行性) exec2(执行JobB(由每个JobA内的列表生成):每个JobA超过800-3000个作业) exec3(执行和准备作业C(由每个作业B生成):每个作业B 2-3个作业) exec4(执行JobD(每个作业1-2个活动)) exec5(等待所有作

ThreadPoolExecutor
ScheduledThreadPoolExecutor
是否线程安全?? 现在,我有一个场景如下:

  • 5
    ThreadPoolExecutor
    (s)
  • exec1(执行JobA(A级作业):最多4-5个作业的并行性)
  • exec2(执行JobB(由每个JobA内的列表生成):每个JobA超过800-3000个作业)
  • exec3(执行和准备作业C(由每个作业B生成):每个作业B 2-3个作业)
  • exec4(执行JobD(每个作业1-2个活动))
  • exec5(等待所有作业完成,然后执行某些活动)
(我希望上述情况是清楚的)

此外,所有执行器在对象级别都是通用的。 在A级,最多只有4-5个作业并行执行,并为下一级(B)各种单个作业/事务做好准备。 B级的工作依次为C级准备工作,C级为D级准备工作

Exec5是一个持久化器,它将所有数据持久化到数据库中

问题是,作业在C&D级别的某个地方丢失了,特别是当有许多并发线程试图异步推送后续执行器任务列表中的新作业时。 所有的
RejectionHandler
s都没有收到任何被拒绝的处理程序。 此外,如果每个
threadpoolexecutor
都减少为一个线程池执行器(仅1
thread
),我也不会遇到任何问题。 作业本身非常小,因此并行性确实为活动提供了显著的优势

我希望我已经说清楚了

请告知。 当做
KT

您如何将工作提交给您的
ExecutorService
?您使用的是
submit(可调用)
还是
execute(可运行)
?在前一种情况下,调用代码负责通过调用返回的
Future
上的
get()
来检测任何异常情况。因此,如果您的执行者只是将工作传递给下一个执行者,并丢弃未来的,则任何错误都不会被检测到

一种解决方法是使用
execute(Runnable)
和重写
ThreadPoolExecutor
afterExecute(Runnable r,Throwable t)
方法,在使用非null
Throwable
调用时发出警报

另一种解决方案是将执行器包装在一个
CompletionService
中,并使用一个专用线程删除已完成的
Future
s和“提取”和异常


顺便说一句,这种结构似乎相当复杂。是否真的需要5级执行人?为什么不从一个执行所有必需步骤的
ThreadPoolExecutor
开始?您的设计越简单,就越容易发现任何问题。

谢谢您的回复。但是,一个ThreadPoolExecutor实际上是不够的。其理念是,只有在完成2级作业后,才需要处理相应的3级作业。此外,还进行定期检查,以确保在完成每个级别后释放资源,最关键的是2级和3级;此外,独立的执行者给出每个阶段待处理任务的确切状态,而不是单独跟踪;按任务设置线程优先级比按作业设置优先级更容易。应尝试afterExecute建议来调试问题。当一个2级作业完成时,为什么不能将一组3级作业提交给同一个执行者?如果在提交3级作业之前需要等待所有2级作业完成,那么为什么不将2级作业提交给完成服务(包装执行者),然后进行轮询,直到所有2级作业完成。在这一点上,你可以提交你的3级工作。代码清晰,每个对象的目的明确。仅仅因为我可以重新提交给同一个调度程序,并不意味着我应该提交给同一个执行者。有了为每个执行者定义的明确目的(表示逻辑步骤完成),管理起来就更容易了。事实上,如果没有这样做,调试可能也会困难得多。此外,如上所述,还有其他因素,如线程优先级设置和关机挂钩附件等,这使得代码逻辑清晰。无论如何,这不会影响结果。对不起,简单地看一下评论,听起来很粗鲁。我不是有意。。。为任何这种无意的感觉道歉,但由于评论中的空间限制,一些文字被编辑。问候你,别担心;没有冒犯!