在Spring MVC中穿过for循环

时间:2015-01-01 10:13:17

标签: java multithreading spring spring-mvc

我有一个Spring MVC应用程序。 我需要实现线程for循环。

情况如下所述。 文件夹中有多个文件,文件夹很多。 必须从每个文件夹并行下载文件。 但必须按顺序下载特定文件夹中的文件。即 如果有N个文件夹,那么在某个时间点,将同时下载N个文件。

示例代码如下所示

private FolderServiceManager folderServiceManager;
private FileRequestService fileRequestService;
......
......
@Override
public void downloadFiles(){
    ExecutorService exec = Executors.newFixedThreadPool(5);
    List<Folder> listOfFolders = folderServiceManager.getAllFolders();
    try {
        for (final Folder folder: listOfFolders) {
            exec.submit(new Runnable() {
                @Override
                public void run() {
                    fileRequestService.downloadMp4Files(folder);
                }
            });
        }
    } finally {
        exec.shutdown();
    }
}

在任何其他代码中不再是并行化。

我的问题是,给定的代码是否适合目的?

spring bean的范围是默认值。我需要改变春豆的范围吗?

2 个答案:

答案 0 :(得分:0)

请考虑使用ThreadPoolExecutor

它将帮助您更好地控制执行。具体来说,您可能希望拥有自定义RejectedExecutionHandler;当您处理文件系统读取时, 很有可能长时间运行/挂起线程,最终可能导致应用程序无法响应。

答案 1 :(得分:0)

我相信代码符合其目的。如果您认为可能会发生这种情况,您可能需要考虑处理长时间运行的线程。

解决问题的另一种方法是使用CompletableFuture类(Java 8)。代码会更清晰(据我所知)。

    // Setup the Executor
    ExecutorService exec = Executors.newFixedThreadPool(5);

    // Create an array of all download jobs
    final CompletableFuture[] downloads = folderServiceManager.getAllFolders()
            .stream()
            .map(folder -> CompletableFuture.runAsync(
                () -> fileRequestService.downloadMp4Files(folder), exec)
             ) // Create the futures
            .toArray(size -> new CompletableFuture[size]); // Collect it as an array

    // If you want to wait for the futures to complete the allOf-method can be used.
    // If you don't want to wait you can skip these lines...
    final CompletableFuture<Void> allDownloads = CompletableFuture.allOf(downloads);
    allDownloads.get();