首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在spring boot Rest API中关闭ExecutorService

在spring boot Rest API中关闭ExecutorService
EN

Stack Overflow用户
提问于 2019-06-21 10:19:45
回答 2查看 5.3K关注 0票数 3

我正在构建一个部署在WebLogic12c上的spring boot rest api应用程序。我的一个需求是对每个传入的请求运行一些长时间运行的任务。传入的rest请求可能会导致多个异步任务执行。

因为我不关心响应,也不关心从这些任务中产生的任何异常,所以我选择使用ExecutorService,而不是Callable或CompletableFuture。

代码语言:javascript
运行
复制
ExecutorService executorService =
  Executors.newFixedThreadPool(2, new CustomizableThreadFactory("-abc-"));

然后,对于我在控制器中收到的传入请求,运行两个for循环,并将这些任务分配给ExecutorService:

代码语言:javascript
运行
复制
for (final String orderId : orderIds) {
        for (final String itemId : itemIds) {               
            exec.execute(new Runnable() {
                public void run() { 
                    try {           
                         //call database operation
                    }catch(Throwable t) {
                       logger.error("EXCEPTION with {} , {}" ,orderId,itemId 
                    )
                }   
            });
        }//for          
    }//for

我的问题是关于关闭ExecutorService的问题。我知道优雅关闭( shutdown )、混合关闭( awaitTermination )或突然关闭( shutdownNow )

对于rest api应用程序,这三者之间的首选方法是什么?

另外,对于可以创建的线程池的数量是否有限制,因为创建的ExecutorService线程池的数量将由传入请求的数量决定

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-21 11:11:17

我们目前有类似的要求,这是一个很难解决的问题,因为如果你想使用正确的锤子。对于编排长时间运行的流程,有非常重要的解决方案,例如SpringBatch。

不过,首先,不必费心停止和启动ExecutorService。这个类的全部意义在于将线程管理的负担从你的手中转移出来,这样你就不需要自己创建和停止线程了。所以你不需要管理经理。

但是要小心你的方法。无需使用队列或其他负载平衡技术来智能地平衡应用程序中跨实例的长时间运行的进程。或者管理一个线程死掉时发生的事情,你可能会陷入麻烦的世界。总的来说,我想说,现在直接与线程或ThreadPools交互,并使用更高级别的解决方案来解决这类问题没有多大意义。

票数 3
EN

Stack Overflow用户

发布于 2019-06-21 11:16:04

awaitTermination通常更安全一些,而shutdownNow更强大。如果您希望executor尽快关闭,通常在函数式方法中使用awaitTermination是个好主意,甚至是runnable,但前提是它完成了创建时要做的所有事情。换句话说,当执行器没有正在执行的活动任务时。例如)

代码语言:javascript
运行
复制
ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime.availableProcessors);
Observable.of(items).schedule(Schedulers.from(executor)).flatMap(item -> {
   ... // this block represents a task that the executor will execute in a worker thread
}).onSubscribe(onNext -> 
   logItem(onNext), throwable -> 
   throwable.printStackTrace(), /* onComplete */ () -> 
   executor.awaitTermination(60, TimeUnit.Seconds)
);
... // you need to shutdown asap because these other methods below are also doing some computation/io-intensive stuff

现在,当此方法完成时,它将调用awaitTermination,如果没有执行任何任务,它将立即关闭池,如果任务仍在执行,则等待长达60秒。

在大多数情况下,线程或工作线程处于非活动状态的时间为60秒,因为这通常是默认的。

另一方面,如果您希望在抛出异常(举一些例子)、出现安全漏洞或另一个模块/服务失败时立即停止执行任务,您可能希望使用shutdownNow()立即停止所有任务,而不需要等待。

我的建议是在两者之间进行选择,如果您不希望在出现异常时继续执行任务,则在catch块中使用shutdownNow -即,如果其中一个项没有添加到列表中,则不再有理由将项列表返回给客户端。否则,我建议在try-catch之后使用awaitTermination,将其设置为一分钟,以便在线程池执行完您指定的所有任务后立即安全地将其关闭。但是,只有在您知道executor将不再负责执行更多任务的情况下,才能这样做。

如果您可以选择简单的shutdown,那么它也是一个好方法。根据甲骨文的文档,shutdown将拒绝所有传入的任务,但会等到当前任务执行完毕。

如果您不确定何时需要关闭executor,最好使用@PreDestroy方法,这样executor就会在您的bean上调用destroy方法之前:

代码语言:javascript
运行
复制
@PreDestroy
private void cleanup(){
   executor.shutdown();
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56696065

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档