簡體   English   中英

如果發生異常,如何停止 Executor 服務中的 Callable 任務

[英]How to stop Callable tasks in Executor service if exception occur

我正在嘗試實現一個示例應用程序來測試 Callable 和 ExecutorService 接口。

在我的應用程序中,我有:

@Bean("fixedThreadPool")
public ExecutorService fixedThreadPool() {
    return Executors.newFixedThreadPool(5);
}

然后:

public void removeUserIds(Set<String> userIds) {
 UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://localhost:8080/remove");
    final List<Callable<String>> callables = new ArrayList<>();  
    userIds.forEach(userId -> {
        final Callable<String> task = () -> callServiceToRemove(builder,userId); //Call to remote service using RestTemplate
        callables.add(task);
    });

    try {
        final List<Future<String>> futureList =
            executor.invokeAll(callables);

        futureList.forEach(future -> {
            try {
                log.info(future.get());
            } catch (final Exception e) {
                log.error("Error : "+ e.getMessage());
            } 
        });
    } catch (final Exception e) {
        log.error("Error Error Error : "+ e.getMessage());
    } finally {
        executor.shutdown();
    }
}

當我使用 100 個用戶 ID 調用 removeUserIds() 方法時,它在愉快的流程中工作正常,但如果服務不可用或關閉,第 100 次將打印錯誤。 如果服務不可用或關閉,我將無法停止/終止線程,因此服務不會發生進一步的調用。 任何人都可以幫助解決這個問題,如果服務關閉,我如何停止線程執行,或者在這里提出可行的解決方案?

在 try catch 塊中移動 callServiceToRemove 調用。

在 catch 塊中,您可以使用 executor.shutdownNow();

shutdownNow()嘗試停止所有正在執行的任務,停止等待任務的處理,並返回等待執行的任務列表。 此方法不會等待主動執行的任務終止並嘗試強制停止它們。 除了盡力嘗試停止處理正在執行的任務之外,沒有任何保證。 此實現通過 Thread.interrupt() 取消任務,因此任何未能響應中斷的任務可能永遠不會終止。

這與其說是編碼問題,不如說是設計問題。 可能有幾種方法。 你可以以這個為例:

使用全局標志

在實際觸發遠程服務調用之前,查找全局布爾標志,例如Globals.serviceUnavailable 這個全局標志可以由遇到遠程錯誤的第一個服務設置。 以下是對代碼的更改。

final Callable<String> task = () -> {
   try{    
       if( !Globals.serviceUnavailable ) callServiceToRemove(builder,userId);
   }
   catch( ServiceUnavailableException e ){ //Or whatever your exception is
       Globals.serviceUnavailable = true; //Notify the remaining tasks that the service is unavailable.
   }

}

當然,您必須查看是否必須同步更新Globals.serviceUnavailable的值。 (如果您可以部分成功刪除一批用戶 ID,則可能沒有必要。)

此外,只有當您的線程池遠小於提交的任務數量時,這才有效,我在這里看到的就是這種情況。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM