多线程下载的原理图
实现的代码
public class MuThreadDownloader {
/**下载线程数量*/
public static int threadCount = 3;
public static int runningThread = 3;
public static void main(String[] args) throws IOException {
String spec = "http://localhost:8083/aliww.exe";
URL url = new URL(spec);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(4000);
conn.setRequestMethod("GET");
int code = conn.getResponseCode();
if(code == 200){
int length = conn.getContentLength();
System.out.println("fileSize:" + length);
/**随机操作文件类*/
RandomAccessFile raf = new RandomAccessFile("阿里旺旺.exe", "rwd");
/**在本地创建一个同样大小的临时文件*/
raf.setLength(length);
raf.close();
/**每个线程下载的大小*/
int blockSize = length / threadCount;
for (int threadId = 1; threadId <= threadCount; threadId++) {
//每个线程下载的起始位置
int startIndex = (threadId - 1) * blockSize;
//每个线程下载的结束位置
int endIndex = threadId*blockSize - 1;
if(threadId == threadCount){
endIndex = length;
}
new DownLoaderThread(startIndex, endIndex, spec,threadId).start();
System.out.println("startIndex-endIndex " + startIndex + "-" + endIndex);
}
}
}
public static class DownLoaderThread extends Thread{
private int startIndex;
private int endIndex;
private String path;
private int threadId;
public DownLoaderThread(int startIndex, int endIndex, String path,int threadId) {
this.startIndex = startIndex;
this.endIndex = endIndex;
this.path = path;
this.threadId = threadId;
}
@Override
public void run() {
try {
File file = new File(threadId + ".txt");
//每个线程下载之前先判断是否存在记录进度的文件
if(file.exists() && file.length() > 0){
InputStream is = new FileInputStream(file);
byte [] buffer = new byte[1024];
is.read(buffer);
System.out.println(new String(buffer));
startIndex = Integer.parseInt(new String(buffer).trim());
}
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//请求服务器下载部分的资源,指定资源的起始位置
conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
conn.setConnectTimeout(5000);
//从服务器返回全部的资源返回200 部分资源返回206
int code = conn.getResponseCode();
System.out.println("code:" + code);
if(code == 206){
System.out.println("线程-" + threadId + "从" + startIndex + "位置开始下载");
InputStream is = conn.getInputStream();
RandomAccessFile raf = new RandomAccessFile("阿里旺旺.exe", "rwd");
//设置写入文件的起始位置
raf.seek(startIndex);
byte[] buff = new byte[1024];
int len = 0;
//用于记录当前下载的进度
int total = startIndex;
while((len = is.read(buff))!=-1){
raf.write(buff, 0, len);
total += len;
System.out.println("线程-" + threadId + "下载到" + total + "字节");
RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");
accessFile.write(String.valueOf(total).getBytes());
accessFile.close();
// FileOutputStream fos = new FileOutputStream(file);
// fos.write(String.valueOf(total).getBytes());
// fos.flush();
// fos.close();
}
is.close();
raf.close();
runningThread -- ;
System.out.println("线程-" + threadId + "下载完成......");
}
} catch (IOException e) {
e.printStackTrace();
}finally{
if(runningThread == 0){
for (int i = 1; i <= threadCount; i++) {
File file = new File(i + ".txt");
file.deleteOnExit();
}
}
}
}
}
}
要点:
1、告诉服务器要请求部分资源
//请求服务器下载部分的资源,指定资源的起始位置
conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);