我有一个服务,它使用ScheduledExecutorService为用户调度异步任务。每个用户将触发该服务来调度两个任务。(第一任务调度具有固定延迟(例如10秒间隔)的第二个任务)伪码代码说明:
task1Future = threadPoolTaskScheduler.schedule(task1);
for(int i = 0; i< 10000; ++i) {
task2Future = threadPoolTaskScheduler.schedule(task2);
task2Future.get(); // Takes long time
Thread.sleep(10);
}
task1.Future.get();假设我有10000用户同时使用该服务,我们可以为我的服务配置两种ScheduledExecutorService:
我能想到的第一种方法是:
优点:
缺点:
关于第二种方法我能想到什么
优点:
缺点:
对哪条路更好有什么想法吗?
发布于 2022-03-06 17:16:41
单个ScheduledExecutorService驱动许多任务
ScheduledExecutorService的全部目的是在经过一定时间之后维护要执行的任务集合。
因此,考虑到您描述的场景,您只需要一个ScheduledExecutorService对象。将您的10,000个任务提交到该对象。每个任务大约在其指定延迟过去时执行。简单又简单。
线程池大小
真正的问题是决定给ScheduledExecutorService分配多少个线程。
当前在OpenJDK项目中实现的线程直接映射到宿主OS线程。这使得它们在CPU和内存使用方面相对重量级。换句话说,当前Java线程是“昂贵的”。
计算线程池大小没有简单的简单答案。最优的数量是最小的线程数量,可以跟上工作负载,而不过度负担主机的有限数量的核心和有限的内存。如果搜索堆栈溢出,就会发现许多关于决定在池中使用多少线程的讨论。
工程织机
并密切关注https://wiki.openjdk.java.net/display/loom/Main的进展及其将虚拟线程引入Java的承诺。这种技术有可能从根本上改变决定线程池大小的演算。使用CPU和内存,虚拟线程将更加高效。换句话说,虚拟线程将相当“便宜”,“便宜”。
执行者服务是如何工作的
你说过:
输入第一个任务,然后尝试调度第二个任务,然后发现没有可用的线程来调度第二个任务。
这不是计划执行器服务(SES)的工作方式。
如果当前由SES执行的任务需要自行调度,或者其他一些任务需要稍后执行,则将提交的任务添加到SES内部维护的队列中。没有必要立即有一个线程可用。除了队列添加之外,什么都不会立即发生。稍后,当添加的任务的指定延迟已经过去时,SES将在其线程池中寻找一个可用的线程来执行该任务,该任务在时间上排队了一段时间。
您似乎需要在特定线程上管理每个任务的执行时间。但这是预定执行者服务的工作。SES跟踪提交执行的任务,注意它们指定的延迟何时过去,并从托管线程池中在线程上调度它们的执行。你不需要处理任何事情。唯一的挑战是为池分配适当数量的线程。
多执行者服务
你评论说:
为什么不使用多个ScheduledExecutorService实例
因为在你的场景中,没有好处。你的问题意味着你有许多相似的任务,但没有优先排序。在这种情况下,只需使用一个执行者服务。一个有12个线程的预定执行器服务将得到与3个服务相同的工作量,每个服务有4个线程。
至于多余的线程,它们不是负担。任何没有要执行的任务的线程几乎不需要使用CPU时间。池可能会也可能不会在一段时间后关闭一些未使用的线程。但是这样的策略取决于执行器服务的线程池的实现,并且对我们作为调用程序员是透明的。
如果场景不同,其中一些任务会阻塞很长时间,或者需要对某些任务进行优先级排序,那么您可能希望将这些任务隔离到单独的executor服务中。
在今天的Java中(在使用虚拟线程的Project之前),当线程块中的代码出现时,该线程只会等待解除阻塞。阻塞意味着您的代码正在执行等待响应的操作。例如,对套接字或web服务块进行网络调用、写入存储块和访问外部数据库块。理想情况下,您不会编写阻塞很长时间的代码。但有时候你必须。
在某些任务运行时间很长的情况下,或者相反,有些任务必须优先执行才能快速执行,那么是的,使用多个executor服务。
例如,假设您有一台16核计算机,除了您的Java应用程序之外,没有什么其他的运行。对于长期运行的任务,您可能有一个最大线程池大小为4的executor服务;对于多个运行的任务,您可能有一个线程池的最大大小为7的执行器服务;对于很少运行但必须快速运行的任务,可能有一个线程池最大大小为2的执行程序服务。(这里的数字是任意的例子,而不是建议。)
其他方法
作为评论,还有其他管理并发的框架。这里讨论的ScheduledExecutorService是通用的。
https://stackoverflow.com/questions/71371997
复制相似问题