多线程加速下载原理:
1,服务器资源是固定的,开启的线程越多,抢占的资源越多
2,宽带的带宽
3,服务器的限制
private void downloadApk() {
try {
private static int threadCount = 3;
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(3000);
int code = conn.getResponseCode();
int fileLength = 0;
if (code == 200) {
//1.获取服务器资源文件的大小
fileLength = conn.getContentLength();
//在本地创建一个相同大小的空文件
RandomAccessFile raf = new RandomAccessFile(getFilePath(), "rw");
raf.setLength(fileLength);
raf.close();
}
//2.开启多个线程对应服务器的一块儿资源
//每个线程下载的区块儿大小
int blockSize = fileLength/threadCount;
for (int threadId = 0; threadId < threadCount; threadId++) {
int startIndex = threadId * blockSize;
int endIndex = (threadId + 1) * blockSize - 1;
//最后一个线程结束位置
if (threadId == threadCount - 1) {
endIndex = fileLength - 1;
}
new downloadThread(startIndex, endIndex, threadId).start();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
static class downloadThread extends Thread {
//开始位置
int startIndex;
//结束位置
int endIndex;
//线程id
int threadId;
//断点的位置
int lastDownPos;
public downloadThread(int startIndex, int endIndex, int threadId) {
super();
this.startIndex = startIndex;
this.endIndex = endIndex;
this.threadId = threadId;
//初始化
lastDownPos = startIndex;
}
@Override
public void run() {
super.run();
//每个线程下载一个对应的服务器资源区块儿
try {
//读取存储的断点的位置
File file = new File(getTempFilePath(threadId));
if (file.exists() && file.length() > 0) {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
//获取断点上次存储的位置
lastDownPos = Integer.valueOf(br.readLine());
//修改开始下载的位置
startIndex = lastDownPos;
br.close();
}
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(3000);
//设置当前线程请求资源的范围
conn.setRequestProperty("Range", "bytes = " + startIndex + "-" + endIndex);
int code = conn.getResponseCode();
InputStream is = conn.getInputStream();
if (code == 206) {
RandomAccessFile raf = new RandomAccessFile(getFilePath(), "rw");
//定位写文件的位置
raf.seek(startIndex);
//读取流
byte[] buffer = new byte[1024 * 8];
int lenth= -1;
while ((lenth = is.read(buffer)) != -1) {
raf.write(buffer, 0, lenth);
//存储断点的位置
RandomAccessFile r = new RandomAccessFile(getTempFilePath(threadId), "rw");
//用临时文件存储相对于整个文件的位置
lastDownPos += lenth;
r.write(String.valueOf(lastDownPos).getBytes());
r.close();
}
raf.close();
}
//3,每个线程都干完活 , 整个资源就下载完了
file.delete();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static String getFilePath() {
int index = path.lastIndexOf("/") + 1;
return path.substring(index);
}
public static String getTempFilePath(int threadId) {
return getFilePath() + threadId + ".txt";
}
多线程下载与单线程下载是一样的,无非是多了一个循环,自己控制开启的线程数
断点只是定义了一个Int类型的变量,把控它的位置,细心+耐心,everyone can do it.