Spring Boot 如果我们需要单独处理每个线程的超时,使用ExecutorService的最佳方式

o2gm4chl  于 2023-06-05  发布在  Spring
关注(0)|答案(1)|浏览(218)

下面是我使用ExecutorService的代码实现

public void startDownloading(DownloadInfo downloadInfo) {
    int messageSentToNextQueue = 0;
    ExecutorService downloadExecutor = Executors.newSingleThreadExecutor();
    try {
            Callable<Integer> task = () -> {
                return fileDownloader.downloadFromSourceLink(downloadInfo);
            };
            Future<Integer> future = downloadExecutor.submit(task);
            try {
                if (downloadInfo.getExtension().equals(ScraperConstant.ZIP_EXTENSION)) {
                        
                    messageSentToNextQueue = future.get(11, TimeUnit.HOURS);

                } else if (downloadInfo.getExtension().equals(ScraperConstant.HTML_EXTENSION)) {
                        
                    messageSentToNextQueue = future.get(10, TimeUnit.MINUTES);

                } else {
                    messageSentToNextQueue = future.get(30, TimeUnit.MINUTES);
                }
            } catch (Exception e) {
                log.error(ex);
                downloadExecutor.shutdownNow();
            }
    } catch (Exception ex) {
        log.error(ex);

    } finally {
        if (!downloadExecutor.isShutdown()) {
            downloadExecutor.shutdownNow();
        }
    }
}

现在,我在每个方法调用上使用SingleThreadExecutor创建ExecutorService,因为在超时的情况下,我可以关闭服务以释放所有底层资源并停止任何进一步的处理。
如果我使用ThreadPoolExecutor并在类级别初始化它并重用它,这肯定是一种更好的方法,但在这种情况下,如果超时发生,我必须关闭完整的ExecutorService以释放资源,这将导致其他线程在该ExecutorService下处理时也停止,我还必须在关闭后初始化ExecutorService。
如果有人提出更好的方法,那就太好了。

bvjxkvbb

bvjxkvbb1#

样式注解:
我不会在三个地方重复messageSentToNextQueue = future.get(...)调用。我也不会在startDownloading函数中编码不同的超时。我会把它们放在downloadInfo中。

messageSentToNextQueue = future.get(
    downloadInfo.getTimeoutValue(),
    downloadInfo.getTimeoutUnit()
);

相关问题