Java多线程下载
package com.orange;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
public class Downloader {
private URL url; // 目标地址
private File file; // 本地文件
private static final int THREAD_AMOUNT = 20; // 线程数
private static final String DOWNLOAD_DIR_PATH = "/home/orange/桌面/"; // 下载目录
private int threadLen; // 每个线程下载多少
private volatile int downloadlen;
private int totalLen;
private volatile long sun;
public Downloader(String address, String filename) throws IOException { // 通过构造函数传入下载地址
url = new URL(address);
File dir = new File(DOWNLOAD_DIR_PATH);
if (!dir.exists()) {
dir.mkdirs();
}
file = new File(dir, filename);
}
public long download() throws IOException {
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
totalLen = conn.getContentLength(); // 获取文件长度
threadLen = (totalLen + THREAD_AMOUNT - 1) / THREAD_AMOUNT; // 计算每个线程要下载的长度
System.out.println("totalLen=" + totalLen + ",threadLen:" + threadLen);
RandomAccessFile raf = new RandomAccessFile(file, "rws"); // 在本地创建一个和服务端大小相同的文件
raf.setLength(totalLen); // 设置文件的大小
raf.close();
for (int i = 0; i < THREAD_AMOUNT; i++) // 开启3条线程, 每个线程下载一部分数据到本地文件中
new DownloadThread(i).start();
return this.sun;
}
private class DownloadThread extends Thread {
private int id;
public DownloadThread(int id) {
this.id = id;
}
public void run() {
long startdate = System.currentTimeMillis();
int start = id * threadLen; // 起始位置
int end = id * threadLen + threadLen - 1; // 结束位置
System.out.println("线程" + id + "下载的范围:\t" + start + "-" + end);
try {
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestProperty("Range", "bytes=" + start + "-" + end); // 设置当前线程下载的范围
InputStream in = conn.getInputStream();
RandomAccessFile raf = new RandomAccessFile(file, "rws");
raf.seek(start); // 设置保存数据的位置
byte[] buffer = new byte[102400];
int len = 0;
while ((len = in.read(buffer)) != -1) {
raf.write(buffer, 0, len);
downloadlen = downloadlen + len;
System.out.println("当前下载进度\t" + downloadlen + "/" + totalLen+"\t\t\t" + (downloadlen/totalLen)*100 + "%\r" );
}
raf.close();
long enddate = System.currentTimeMillis();
sun = sun + (enddate - startdate);
System.out.println("线程" + id + "下载完毕,耗时" + (enddate - startdate) + "毫秒");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
String add = "http://hub.meefik.ru/rootfs/alpine_arm64.tgz";
long sun = new Downloader(add, "alpine_arm64.tgz").download();
System.out.println(sun);
}
}