【问题标题】:Parallelize a network bound for-loop in Java在 Java 中并行化网络绑定 for 循环
【发布时间】:2017-07-05 23:24:47
【问题描述】:

我有一个包含 100 万个文件名的列表,我必须从 S3 下载这些文件名。目前我正在逐个下载每个文件(下面的for循环),下载完成大约需要4天。

    for (String fileName : Files) {
        InputStream is = null;
        try {
            is = m_S3.downloadFile(fileName); // m_s3 is a wrapper around AmazonS3 client
            m_localDisk.createFile(fileName, is); // m_localDisk is an interface for local disk storage.
        } 
        catch (Exception e) {
            System.out.println("Exception happened");
        }
        finally {
            is.close();
        }
    }

由于S3 允许并行连接,我计划并行下载。我怎样才能在Java 中做到这一点?我在C 中使用Pthread 做了类似的事情,我只是在其上下文中将输入和委托线程与输入的不同部分分开。我可以在 Java 中做到这一点,但我确信有更好、更高级别的方法来做到这一点。

我考虑过使用parallelStreams 之类的事情,但由于它只是使用管道机制,我认为它不会给我带来太大的改进——一次只能打开一个到S3 的网络连接。

【问题讨论】:

  • 可能以Executors/ExecutorService开头
  • 如果它是网络捆绑,并行化将产生完全零收益。
  • 可能我对“网络绑定”的使用不正确。我的意思是,这需要最多的时间。所以如果我可以并行下载,整个方法会加快速度。

标签: java multithreading


【解决方案1】:

使用parallelStream 可能是解决此问题的最简单方法。
默认 AmazonS3Client 最多可处理 50 个并发连接,但您可以对其进行不同的配置。

默认情况下,parallelStream() 使用共享系统线程池,numOfProcessors -1 线程,以下方法创建您自己的线程池,您可以根据自己的需要调整大小,加上长时间运行的阻塞任务不会干扰在系统池上运行其他东西。

List<String> fileNames = ...
ForkJoinPool forkJoinPool = new ForkJoinPool(4);
forkJoinPool.submit(()-> {
    fileNames.parallelStream().forEach(fileName -> {
        try(InputStream is = m_S3.downloadFile(fileName)) {
            m_localDisk.createFile(fileName, is);
        } catch (IOException e) {
            e.printStackTrace();
        }
    });
}).get();

【讨论】:

  • 我希望我的客户升级到 Java8
猜你喜欢
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 2016-07-23
  • 2017-03-17
相关资源
最近更新 更多