简单的android多线程下载

一.多线程下载
1.为什么使用多线程下载
开启多个线程下载可以占用服务端更多的资源, 提高下载速度(速度达到极限时,多线程和单线程速度差别不大)
2.怎么多线程下载
在下载的时候开启多条线程
每条线程设置请求头"Range", 请求服务端数据的一部分
使用RandomAccessFile的seek()方法写到本地文件的指定位置
public class DownService {
private String source;//
private Handler handler;
private URL url;
private String filename;// 文件名
private long threadlength;// 每条现成下载的总长度
private final static int AMOUNT = 3;// 分三条现成下载
private long currentlength; // 当前总共完成了多少


private File file;


public DownService(String source, Handler handler) throws Exception {
this.source = source;
this.handler = handler;
filename = source.substring(source.lastIndexOf("/") + 1);
System.out.println("filename" + filename);
url = new URL(source);//所需要下载的文件(直接从服务器上获取)


}
// 用randomaccess来实现多线程下载
// 首先定义一个下载方法,然后开启多个线程来实现下载
public void download() throws Exception {
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(3000);
// 获取文件的长度,好分断下载
long totallength = conn.getContentLength();// 获取文件的总长度
System.out.println(totallength);
Message msg = new Message();
msg.what = 1;// 设置标识码
msg.getData().putLong("totallength", totallength);
handler.sendMessage(msg);// 把最大数据发送到主线程中
----与主线程通信,将文件的长度发给主线程----------(handler handmessage())
file = new File("/mnt/sdcard/" + filename);
threadlength = (totallength + AMOUNT - 1) / AMOUNT;// 设置每一个现成下载的大小
RandomAccessFile raf = new RandomAccessFile(file, "rws");// 每读取一个字节,就会存储一个字节rws模式
raf.setLength(totallength);// 设置文件的大小
raf.close();
// 开启数个现成,来实现下载
for (int i = 0; i < AMOUNT; i++) {
// 开启线程下载
new ThreadDown(i).start();
}
}


private class ThreadDown extends Thread {
private int x;


ThreadDown(int x) {
this.x = x;
}
// 开启一个线程下载
public void run() {
long start = x * threadlength; // 一个现成下载的开始位置 即randomaccess流开始写入的位置
long end = x * threadlength + threadlength - 1;// 一个线程下载结束的位置即randomaccess流关闭的位置,如果文件写完了,则自动关闭
HttpURLConnection conn;
try {
conn = (HttpURLConnection) url.openConnection();//每一个线程获取一个连接,多个同时下载。
conn.setConnectTimeout(3000);


conn.setRequestProperty("Range", "bytes=" + start + "-" + end); // 在请求头中   设置当前线程下载的范围
// 获取输入流,开始写文件


InputStream in = conn.getInputStream();
RandomAccessFile raf = new RandomAccessFile(file, "rws");//每读取一段数据就存储rws模式
raf.seek(start);// 设置文件开始的位置
int len;
byte[] buf = new byte[1024 * 100];// 每次读取100k
while ((len = in.read(buf)) != -1) {
synchronized (DownService.this) { // 多个下载线程之间同步
currentlength += len; // 统计所有线程总共完成了多少
// 发送当前进度
Message msg = new Message();
msg.getData().putLong("currentlength", currentlength);
msg.what = 2;
handler.sendMessage(msg);
}
raf.write(buf, 0, len);// 写到本地
}
raf.close();
// 不能关闭输入流,文件未写完
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

你可能感兴趣的:(简单的android多线程下载)