用Java下载多个文件

时间:2017-05-03 17:29:25

标签: java multithreading download

我有一个程序需要从网页下载小文本文件,我写了以下代码:

URLConnection connection = null;    // Connection to the URL data
InputStreamReader iSR = null;       // Stream of the URL data
BufferedReader bR = null;           // Reader of URL data
URL url = null;                     // URL based on the specified link

// Open the connection to the URL web page
url = new URL(urlLink);
connection = url.openConnection();

// Initialize the Readers
iSR = new InputStreamReader(connection.getInputStream());
bR = new BufferedReader(iSR);

// Fetch all of the lines from the buffered reader and join them all
// together into a single string.
return bR.lines().collect(Collectors.joining("\n"));

不幸的是,我从中下载数据的服务器有很长的TTFB等待时间。根据开发人员工具(F12),大约90%的总下载时间是TTFB。如果我要下载大量文件,这使得在我的Java程序中下载速度极慢。基本上,对于每个文件,我们打开一个连接,等待250毫秒,下载,打开一个连接,等待另一个250毫秒,下载,这对于大量文件来说非常慢。我能够使用线程减少问题,这样我就有大约10个线程,每个线程都下载了我需要的所有文件的一部分。这加快了我的计划,但它并没有解决我遇到的根本问题。每个线程仍然需要打开一个连接,等待250ms,下载并重复。我理想的解决方案是以某种方式同时发送所有请求并等待250ms以完成TTFB时间,然后分别从网页下载所有数据。我能想到这样做的唯一方法是创建1000个线程并在每个线程上打开一个URL连接,但这似乎是一个非常糟糕的方法。有没有其他方法可以打开多个URL连接并让TTFB期间同时发生?

2 个答案:

答案 0 :(得分:1)

我认为你走在正确的轨道上。启动几个线程以减少总TTFB等待时间听起来是个好主意。为了避免启动极端数量的线程,您可以考虑使用类似Object Pool Pattern的设计模式来将一次激活的线程数量限制为一定数量。

答案 1 :(得分:0)

1000个线程将占用500-1000兆字节的核心内存。这是这种方法的唯一缺点。如果您的计算机有足够的内存,这是最简单,最可靠的解决方案。 如果您不想花费这么多内存(特别是如果您想要更多同时连接),那么您可以使用Java NIO API。它有2种口味,Nio1和Nio2。 Nio1太复杂而无法直接使用它,但是有许多包装器库,例如网状。 Nio2可以直接使用。在任何一种情况下,您都可以大大减少内存消耗并保持合理的工作线程数(例如,等于处理器内核的数量)。