并行化Java中的网络绑定循环

时间:2017-07-05 23:24:48

标签: java multithreading

我有一个包含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的网络连接将在一段时间。

1 个答案:

答案 0 :(得分: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();