# thunder **Repository Path**: hztv/thunder ## Basic Information - **Project Name**: thunder - **Description**: 一个简单、快速、可扩展的多任务 多线程下载器 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 3 - **Created**: 2025-01-05 - **Last Updated**: 2025-01-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## Thunder > 一个简单、快速、可扩展的多任务 _多线程下载器_ #### 环境 + Jdk11 + Maven3.8.x #### 支持协议 + Http/1.1 #### 简单示例 + 极简启动 ```java Thunder.me() .schedule("https://ks-xpc4.xpccdn.com/5117a9fe-df5b-4670-90fb-87911b28a7e0.mp4", "D:\\mydd\\张国荣.mp4") .schedule("https://ks-xpc4.xpccdn.com/fe8f0e83-8d83-474d-8642-43dbf616684c.mp4", "D:\\mydd\\微博钱包.mp4") .schedule("https://ks-xpc17.xpccdn.com/82bbe85d-0683-4af3-91e8-cb3621f93f1f.mp4", "D:\\mydd\\五月天走心纪录短片.mp4") .schedule("https://ks-xpc4.xpccdn.com/b9a664a9-8f02-46cb-85e4-08c5e6d217eb.mp4", "D:\\mydd\\1500棵樱花共同绽放.mp4") .schedule("https://ks-xpc4.xpccdn.com/ad25a35b-bbe2-4212-8d96-4ce0d0203206.mp4", "D:\\mydd") .run(); ``` + 单线程下载 ```java Thunder.me() // 这里代表单线程下载 .single() .schedule("https://ks-xpc4.xpccdn.com/5117a9fe-df5b-4670-90fb-87911b28a7e0.mp4", "D:\\mydd\\张国荣.mp4") .schedule("https://ks-xpc4.xpccdn.com/fe8f0e83-8d83-474d-8642-43dbf616684c.mp4", "D:\\mydd\\微博钱包.mp4") .run(); ``` + 指定线程数 ```java Thunder.me() // 启动100个线程 .multi(100) .schedule("https://ks-xpc4.xpccdn.com/5117a9fe-df5b-4670-90fb-87911b28a7e0.mp4", "D:\\mydd\\张国荣.mp4") .run(); ``` + 指定切片数或切片大写(注意!两者不能同时存在,后面的会覆盖前面) ```java Thunder.me() // 切片2个 .sharingNum(2) .schedule("https://ks-xpc4.xpccdn.com/5117a9fe-df5b-4670-90fb-87911b28a7e0.mp4", "D:\\mydd\\张国荣.mp4") .run(); // 或者指定切片大小 Thunder.me() .sharingUnitByKB(1024 * 1024 * 2L) .schedule("https://ks-xpc4.xpccdn.com/5117a9fe-df5b-4670-90fb-87911b28a7e0.mp4", "D:\\mydd\\张国荣.mp4") .run(); ``` + 指定切片重试次数 ```java Thunder.me() .reties(3L) .schedule("https://ks-xpc4.xpccdn.com/5117a9fe-df5b-4670-90fb-87911b28a7e0.mp4", "D:\\mydd\\张国荣.mp4") .run(); ``` #### 与Giee上其他多线程下载器对比 (仅供参考) + 选取对比的下载器地址:[fast-download](https://gitee.com/silently9527/fast-download) + 以下本项目称为: **Thunder**, 对比的下载器称为:**FastDownload** ###### **速度** 1. 大文件对比 | 文件地址 | 大小 | | --- | --- | | [http://mirrors.163.com/centos/8-stream/isos/x86_64/CentOS-Stream-8-x86_64-20210728-dvd1.iso](http://mirrors.163.com/centos/8-stream/isos/x86_64/CentOS-Stream-8-x86_64-20210728-dvd1.iso) | 9.61(GB) | + **Thunder** + 线程数:50 + 耗时:884184ms (884.184s) + ![效果图](./img/iso-thunder.jpg) + **FastDonwload** + 线程数:50 + 耗时:914s + ![效果图](./img/iso-fastdownload.jpg)

2. 小文件对比 | 文件地址 | 大小 | | --- | --- | | [https://ks-xpc4.xpccdn.com/5117a9fe-df5b-4670-90fb-87911b28a7e0.mp4](https://ks-xpc4.xpccdn.com/5117a9fe-df5b-4670-90fb-87911b28a7e0.mp4) | 35.68(MB) | + **Thunder** + 线程数:1 + 耗时:3629ms (3.629s) + **FastDownload** + 线程数:1 + 耗时: 3s 可以看到,速度方面是差不多的。 ###### **API设计** + **Thunder** 统一管理 + 支持单线程 + 支持设置线程数 + 支持设置切片数 + 支持设置切片大小 + 支持重试 + 支持自定义切片算法 + 支持自定义数据写入方式 + 支持错误回调 + 支持多地址 …… ```java Thunder.me() .sharingNum(1) .sharingUnitByKB(1024) .single() .multi(50) .reties(3L) .downloadHandler(new DefaultDownloadHandler() { @Override public List partition(long id, long size, boolean isRange, String address) { // 你的逻辑 return null; } }) .schedule("https://ks-xpc4.xpccdn.com/5117a9fe-df5b-4670-90fb-87911b28a7e0.mp4", "D:\\mydd\\张国荣.mp4") .schedule("https://ks-xpc4.xpccdn.com/fe8f0e83-8d83-474d-8642-43dbf616684c.mp4", "D:\\mydd\\微博钱包.mp4") .run(); ``` + **FastDownload** 多个不同实例 + 支持单线程 + 支持设置线程数 + 支持自定义进度打印 + 支持单线程,内存缓存依次写入 ```java String fileURL = ""; // 内存写 SimpleDownloader simpleDownloader = new SimpleDownloader(); simpleDownloader.download(fileURL, "D:\\Video"); //单线程下载 Downloader downloader = new FileDownloader(); downloader.download(fileURL, "/Users/huaan9527/Desktop"); // 多线程下载,设置线程数据和自定义打印 MultiThreadDownloadProgressPrinter downloadProgressPrinter = new MultiThreadDownloadProgressPrinter(50); Downloader downloader = new MultiThreadFileDownloader(50, downloadProgressPrinter); downloader.download(fileURL, "D:\\Video"); ``` ###### **第三方依赖管理** + **Thunder** [无依赖] + **FastDownload** [依赖 Spring] ###### **实现差异** + **Thunder** + 默认,大小文件、多单线程数据写入都采用同一个文件随机写入。 + **FastDownload** + 默认,大文件、多线程每个线程数据写入临时文件,然后合并所以临时文件。 + 默认,小文件、单线程先缓存内存,然后依次同一个文件。(必须是单线程,确保写入顺序) >Tips: 如果Thunder要实现内存缓存、多临时文件合并也很简单,如实现内存缓存代码: ```java // 实现内存缓存代码。目前已内置 public class MemoryDownloadHandler extends DefaultDownloadHandler { private final ConcurrentHashMap dataCache = new ConcurrentHashMap<>(); @Override public void data(InputStream inputStream, DownloadTask downloadTask, ShardingTask shardingTask) throws Exception { byte[] bytes = inputStream.readAllBytes(); dataCache.put(shardingTask.getOffset(), bytes); System.out.println("[下载完成@" + shardingTask.getId() + "#" + shardingTask.getOffset() + "] - " + shardingTask); } @Override public void completed(DownloadTask task) { final Path path = Paths.get(task.getLocation()); dataCache.entrySet().stream() .sorted(Map.Entry.comparingByKey()) .map(Map.Entry::getValue) .forEach(bytes -> { try { Files.write(path, bytes, StandardOpenOption.CREATE, StandardOpenOption.APPEND); } catch (IOException e) { // ignore } }); dataCache.clear(); super.completed(task); } } // 创建下载器 Thunder.me() // 使用内存模式,防止内存溢出和数据混乱 .memoryCacheMode() .downloadHandler(new MemoryDownloadHandler()) .schedule("https://ks-xpc4.xpccdn.com/5117a9fe-df5b-4670-90fb-87911b28a7e0.mp4", "D:\\Video\\aa.mp4") .run(); // 注意,与FastDownload不同的是: // 1、依旧是多线程 // 2、依旧支持多任务 ``` ## TODO + 持久化下载历史 + 持久化下载点 + 支持手动重试 + 支持首次启动下载之前未下载点 + 优化下载进度显示