在Android之中呢,对于多线程的操作很是平凡,所以对于多线程的理解越深,那么对于自己的程序便能够很好的运行
这也是对于Android开发是一个重要的知识点,那么我们现在来了解多线程的下载原理。
android 多线程下载
多线程下载步骤:
1.本地创建一个跟服务器一样的大小一样的文件 临时文件。
2.计算分配几个线程去下载服务器上的资源 每个文件下载的位置。
3.开启线程,每一个线程下载对应的文件。
4.如果所有的线程都把自己的数据下载完成了,服务器上的资源就被下载到本地了
如图所示:(假设有三个线程在进行下载)
服务器端:
0 1 2 3 4 5 6 7 8 9
1.文件的长度/3,得到每个线程下载文件的长度。(假设有三个线程进行下载)
线程1:下载 0-2
线程2:下载 3-5
线程3:下载 6-到文件末尾
每一个文件下载的位置计算方式
开始位置:
(线程id - 1) * 每一个快的大小
结束位置:
(线程id)* 每一快的大小 - 1
下面,我们先用java代码来实现一下
package com.zengtao.demo;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
public class DemoLoader {
private static DemoLoader loader = new DemoLoader();
private static int threadCount = 3;
private DemoLoader() {
}
// 单例设计模式
public static DemoLoader getInstance() {
return loader;
}
public void downFile(String path) {
// 去服务器端获取文件的长度,在本地创建一个跟服务器一样大小的文件
try {
URL url = new URL(path);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setDoInput(true);
connection.setRequestMethod("GET");
connection.setReadTimeout(5000);
int code = connection.getResponseCode();
if (code == 200) {
// 获取服务器端文件的长度
int fileLength = connection.getContentLength();
// 本地创建一个跟服务器一样大小的文件
RandomAccessFile raf = new RandomAccessFile("setup.ext", "rwd");
raf.setLength(fileLength);
raf.close();
// 假设三个线程下载
int blockSize = fileLength / threadCount;
for (int threadId = 0; threadId < threadCount; threadId++) {
int startIndex = (threadId - 1) * blockSize;
int endIndex = threadId * blockSize - 1;
if (threadId == threadCount) {
endIndex = fileLength;
}
System.out.println("线程:" + threadId + ",下载:" + startIndex
+ "--->" + endIndex);
// 开始下载
new DownLoadThread(threadId, startIndex, endIndex, path)
.start();
}
System.out.println("文件总长度为:" + fileLength);
} else {
System.out.println("请求失败!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 下载文件的主线程
*
* @author Administrator zengtao
*
*/
public class DownLoadThread extends Thread {
private int threadId;
private int startIndex;
private int endIndex;
private String path;
/**
*
* @param threadId
* 线程id
* @param startIndex
* 线程下载开始位置
* @param endIndex
* 线程下载结束位置
* @param path
* 线程下载结束文件放置地址
*/
public DownLoadThread(int threadId, int startIndex, int endIndex,
String path) {
super();
this.threadId = threadId;
this.startIndex = startIndex;
this.endIndex = endIndex;
this.path = path;
}
@Override
public void run() {
super.run();
URL url;
try {
url = new URL(path);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
// 请求服务器下载部分的文件,制定开始的位置,和结束位置
connection.setRequestProperty("Range", "bytes=" + startIndex
+ "-" + endIndex);
connection.setDoInput(true);
connection.setRequestMethod("GET");
connection.setReadTimeout(5000);
// 从服务器获取的全部数据,返回:200,从服务器获取部分数据,返回:206
int code = connection.getResponseCode();
System.out.println("code = " + code);
InputStream is = connection.getInputStream();
RandomAccessFile raf = new RandomAccessFile("setup.exe", "rwd");
// 随机写文件的时候,从什么时候开始
raf.seek(startIndex);
int len = 0;
byte[] buff = new byte[1024];
while ((len = is.read(buff)) != -1) {
raf.write(buff, 0, len);
}
is.close();
raf.close();
System.out.println("线程:" + threadId + ",下载完成");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
要使用该类的时候,只需要知道一个url地址,然后调用里面的downFile()方法,就会开始下载文件了,这样实现可以下载一个安装包,比如:在网上下载一个qq,微信等的安装包,自己安装到电脑上,便可以用该方法实现。