Java 并行化数千次下载的最佳方法
我正在创建一个应用程序,在这个应用程序中,我必须使用Java下载数千个图像(每个图像约1 MB) 我在REST请求中获取相册URL列表,每个相册包含多个图像 所以我的请求看起来像:Java 并行化数千次下载的最佳方法,java,multithreading,java-stream,completable-future,fileutils,Java,Multithreading,Java Stream,Completable Future,Fileutils,我正在创建一个应用程序,在这个应用程序中,我必须使用Java下载数千个图像(每个图像约1 MB) 我在REST请求中获取相册URL列表,每个相册包含多个图像 所以我的请求看起来像: [ "www.abc.xyz/album1", "www.abc.xyz/album2", "www.abc.xyz/album3", "www.abc.xyz/album4", "www.abc.xyz/a
[
"www.abc.xyz/album1",
"www.abc.xyz/album2",
"www.abc.xyz/album3",
"www.abc.xyz/album4",
"www.abc.xyz/album5"
]
假设每个相册都有1000张图片,那么我需要并行下载50000张图片
现在我已经使用parallelStream()
实现了它,但我觉得我可以进一步优化它
有两个基本类-AlbumDownloader
和ImageDownloader
(弹簧组件)
因此,主应用程序在相册列表上创建一个parallelStream()
:
albumData.parallelStream().forEach(ad -> albumDownloader.downloadAlbum(ad));
以及AlbumDownloader->downloadAlbum()方法中的parallelStream()
List<Boolean> downloadStatus = albumData.getImageDownloadData().parallelStream().map(idd -> imageDownloader.downloadImage(idd)).collect(Collectors.toList());
这将创建5个不同的池,每个池包含1000个线程,相当于5000个线程,这可能会降低性能,而不是提高性能
你能给我一些想法使它非常非常快吗
顺便说一下,我正在使用ApacheCommonsIOFileUtils
下载文件,我有一台有12个可用CPU内核的机器
假设每个相册都有1000张图片,那么我需要并行下载50000张图片
认为应用程序并行处理50000件事情是错误的。你要做的是优化你的吞吐量——你要在最短的时间内下载所有的图片
您应该尝试使用一个固定大小的线程池,然后调整池中的线程数量,直到优化吞吐量为止——可能从双倍处理器数量开始。如果您的应用程序主要在等待网络或服务器,那么您可能可以增加池中的线程数,但您不想让服务器过载,从而使其变慢为爬行,也不想让大量线程重击您的应用程序
这将创建5个不同的池,每个池包含1000个线程,相当于5000个线程,这可能会降低性能,而不是提高性能
我认为多个池没有任何意义,除非每个相册都有不同的服务器,或者每个相册的下载量不同的其他原因。使其“非常非常快”的唯一方法是与服务器建立“非常非常快”的网络连接;e、 g.将您的客户端与您正在下载的服务器共同定位
您的下载速度将受到许多潜在瓶颈的限制。这些措施包括:
- 它可能会阻塞您的网络链接,或者
- 它可能会在您从中获取的服务器中触发反占用或反DOS防御
我还建议你确保你有权限做你正在做的事情。从事音乐出版业务的公司都有优秀的律师。如果他们认为你违反了他们的条款和条件或窃取了他们的知识产权,他们可能会让你的生活变得不愉快
1-例如阻止您的IP地址或向您的服务提供商发出删除请求。您考虑过配置文件吗?因为没有这样的神奇数字。上限将由图像服务器的响应时间和internet连接的下载带宽决定。Java的NIO具有异步功能,可以让您节省线程,但我认为您可以节省必要的线程,以完全耗尽服务器容量或带宽。我认为更好的方法是只并行相册而不是图像,如果它们太多,请使用分页。此外,并行或堆栈方式获得1000张图像的速度更快吗?@JohnyDeph-我也想并行下载这些图像。考虑一个场景,我只通过一张包含5000张图像的专辑。我不想让那5000张图片按顺序下载,对吗?每次图像下载都是一个到服务器的新连接(具有确切的图像URL)加上将该图像保存到磁盘的过程的组合。我看不出有任何问题,即使一个线程中有10000个图像。Ok 10000个线程,10000个连接,具有并行行为。第一个问题:如果有多个设备具有相同的并行行为,那么您的数据源将如何?第二个问题:如果你的互联网连接太慢怎么办?你的并行化变得没用了,对吧?第三个问题:连接到数据库,您应该为每个线程创建新的连接,您认为可以吗?对不起,如果我错了
ExecutorService executor = Executors.newFixedThreadPool(Math.min(albumData.getImageDownloadData().size(), 1000));