以下是一个使用Java实现多线程下载器的案例。这个下载器能够读取一个包含多个下载链接的文件,并启动多个线程来并发下载这些资源。
一、项目结构
假设我们的项目结构如下:
MultiThreadDownloader/
│
├── src/
│ └── com/
│ └── example/
│ ├── Downloader.java
│ ├── DownloadTask.java
│ └── Main.java
│
└── resources/
├── download.txt // 包含下载链接的文件
└── config.properties // 配置文件
二、代码实现
- Downloader.java
package com.example;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Downloader {
private int threadNum;
private String targetDir;
// 读取配置文件并初始化
public void start(String propDir) throws IOException {
File propFile = new File(propDir + "/config.properties");
Properties properties = new Properties();
try (Reader reader = new FileReader(propFile)) {
properties.load(reader);
this.threadNum = Integer.parseInt(properties.getProperty("thread-num"));
this.targetDir = properties.getProperty("target-dir");
this.superDownload(propDir + "/download.txt", targetDir);
}
}
// 多线程下载文件并保存到本地
public void superDownload(String downloadTxt, String targetDir) {
File dir = new File(targetDir);
if (!dir.exists()) {
dir.mkdirs();
System.out.println("[INFO] 发现下载目录[" + dir.getPath() + "]不存在, 已自动创建");
}
List<String> resources = new ArrayList<>();
try (BufferedReader bfreader = new BufferedReader(new FileReader(downloadTxt))) {
String line;
while ((line = bfreader.readLine()) != null) {
resources.add(line);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
ExecutorService threadPool = Executors.newFixedThreadPool(this.threadNum);
for (String resource : resources) {
threadPool.execute(new DownloadTask(resource, targetDir));
}
threadPool.shutdown();
}
public static void main(String[] args) throws IOException {
Downloader downloader = new Downloader();
downloader.start("resources/");
}
}
- DownloadTask.java
package com.example;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Paths;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DownloadTask implements Runnable {
private String url;
private String targetDir;
public DownloadTask(String url, String targetDir) {
this.url = url;
this.targetDir = targetDir;
}
@Override
public void run() {
try {
String fileName = extractFileNameFromURL(url);
File file = new File(targetDir, fileName);
try (InputStream inputStream = new URL(url).openStream();
OutputStream outputStream = new FileOutputStream(file)) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
System.out.println("[INFO] 下载完成: " + file.getAbsolutePath());
}
} catch (Exception e) {
System.err.println("[ERROR] 下载失败: " + url + " - " + e.getMessage());
}
}
// 从URL中提取文件名
private String extractFileNameFromURL(String url) {
String regex = "[^/]+$";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(url);
return matcher.find() ? matcher.group() : "downloaded_file";
}
}
- Main.java(可选,如果Downloader中已有main方法,则不需要此文件)
package com.example;
public class Main {
public static void main(String[] args) {
// 这里可以调用Downloader的main方法或者其他方式来启动下载器
}
}
- resources/download.txt
http://example.com/file1.zip
http://example.com/file2.jpg
http://example.com/file3.mp4
- resources/config.properties
thread-num=5
target-dir=D:/downloads
三、运行步骤
-
将上述代码分别保存到对应的Java文件中。
-
确保resources文件夹及其内容(download.txt和config.properties)在项目中的正确位置。
-
使用Java编译器和运行时环境编译并运行Downloader类(或Main类,如果Main类调用了Downloader的main方法)。
四、注意事项
-
线程管理:在实际应用中,需要更好地管理线程池,例如设置合理的线程数量、处理线程异常等。
-
错误处理:本例中的错误处理较为简单,可以根据需要添加更详细的日志记录或重试机制。
-
性能优化:对于大文件下载,可以考虑使用分块下载或断点续传等技术来提高性能和可靠性。
-
安全性:在实际应用中,需要注意URL的合法性验证、防止恶意下载等安全问题。
这个多线程下载器案例展示了如何使用Java多线程技术来实现并发下载多个文件的功能。通过合理的线程管理和错误处理,可以提高下载效率和可靠性。
1203



被折叠的 条评论
为什么被折叠?



