结果和第一篇一样。
原理:在第一篇的基础上添加了存储每个线程的下载进度的临时文件,当全部的线程都下载好的时候,将存储下载进度的临时文件删除
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
public class M1 {
//下载一个文件的线程数
public static int count = 3;
public static String basePath = "C:\\Users\\shixing\\Desktop\\haha\\";
//本地临时文件path
public static String localPath = basePath + "33.jpg";
//下载地址,你替换path的网址就行了
public static String path = "https://img-blog.csdn.net/20160130160136042?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center";
//the number of thread finished.
public static int currentFinished = 0;
public static void main(String[] args) {
URL url;
try {
url = new URL(path);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
connection.setReadTimeout(5000);
connection.setConnectTimeout(5000);
if(connection.getResponseCode() == 200) {
//拿到要下载文件的大小
int length = connection.getContentLength();
//指定临时文件的路径和文件名
File file = new File(localPath);
//创建随机文件存储对象
RandomAccessFile raf = new RandomAccessFile(file, "rwd");
//创建临时文件的大小,和服务器文件一模一样
raf.setLength(length);
//计算每个线程下载的字节数
int size = length / count;
for(int i = 0; i < count; ++i) {
//计算3个线程下载数据的开始位置和结束位置
int startIndex = i * size;
int endIndex = (i + 1) * size - 1;
//如果是最后一个线程,name结束位置做特殊处理
if(i == count - 1) {
endIndex = length - 1;
}
// System.out.println("线程" + i + "的开始位置:" + startIndex
// +"-------结束位置:" + endIndex);
new MyDownloadThread(i, startIndex, endIndex).start();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getFileName(String path2) {
int index = path2.lastIndexOf("/");
return path2.substring(index + 1);
}
}
class MyDownloadThread extends Thread {
int threadId;
int startIndex;
int endIndex;
public MyDownloadThread(int i, int startIndex, int endIndex) {
this.threadId = i;
this.startIndex = startIndex;
this.endIndex = endIndex;
}
@Override
public void run() {
try {
File fileProcess = new File(M1.basePath + this.threadId + ".txt");
int currentPosition = this.startIndex;
if(fileProcess.exists()) {
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(new FileInputStream(fileProcess)));
this.startIndex = Integer.parseInt(bufferedReader.readLine());
currentPosition = this.startIndex;
bufferedReader.close();
System.out.println("线程" + threadId + "的开始位置:" + startIndex
+"-------结束位置:" + endIndex);
}
URL url = new URL(M1.path);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
connection.setReadTimeout(5000);
connection.setConnectTimeout(5000);
//设置请求数据的范围
connection.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
//206说明请求的是部分数据,而200是请求的全部数据
if (connection.getResponseCode() == 206) {
InputStream inputStream = connection.getInputStream();
byte[] b = new byte[1024];
//当前下载的总子节数
int total = 0;
int len = 0;
//指定临时文件的路径和文件名
File file = new File(M1.localPath);
RandomAccessFile raf = new RandomAccessFile(file, "rwd");
//设置线程从哪个位置开始写入数据到临时文件
raf.seek(startIndex);
while((len = inputStream.read(b)) != -1) {
raf.write(b,0,len);
total += len;
System.out.println("线程" + threadId + " 已经下载" + total);
currentPosition = startIndex + total;
RandomAccessFile rafProcessFile = new RandomAccessFile(fileProcess, "rwd");
rafProcessFile.writeBytes(currentPosition + "");
rafProcessFile.close();
}
raf.close();
System.out.println("线程" + threadId + "下载完毕----------");
M1.currentFinished++;
synchronized (M1.class) {
if(M1.currentFinished == M1.count) {
for(int i = 0; i < M1.count; ++i) {
File tempFile = new File(M1.basePath + i + ".txt");
if(tempFile.exists()) {
tempFile.delete();
}
}
M1.currentFinished = 0;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}