我有一个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的范围是默认值。我需要改变春豆的范围吗?
答案 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();