关于多线程:
如果你通过多个线程同时与服务器连接,那么你就可以榨取到较高的带宽了。例如原来有10个用户都通过单一线程与服务器相连,服务器的总带宽假设为56Kbps,则每个用户(每个线程)分到的带宽是5.6Kbps,即0.7K字节/秒。如果你同时打开两个线程与服务器连接,那么共有11个线程与服务器连接,而你获得的带宽将是56/11*2=10.2Kbps,约1.27K字节/秒,将近原来的两倍。你同时打开的线程越多,你所获取的带宽就越大(原来是这样,以后每次我都通过1K个线程连接:P)。当然,这种情况下占用的机器资源也越多。有些号称“疯狂下载”的下载工具甚至可以同时打开100个线程连接服务器。ps:摘自百度百科
package com.example.test_download;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import android.os.Environment;
import android.widget.Toast;
/*path:下载路径
* fillName:文件名
*
*
* */
public class downLoader {
private static int threadcount = 3;// 开启线程数
private static long blocksize;// 每个线程下载的大小
private static int Runningthreadcount;// 用来记录存活线程
public downLoader(final String path, final String fileName)
throws IOException {
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection connection = null;
try {
URL url = new URL(path);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(10000);
connection.connect();
} catch (Exception e) {
System.out.println("网络连接失败");
}
try {
if (connection.getResponseCode() == 200) {
long size = connection.getContentLength();//得到文件大小
System.out.println(size);
blocksize = size / threadcount;//blocksize为平均线程下载大小,threadcount默认为3
File file = new File(Environment
.getExternalStorageDirectory(), fileName);
/*
* 当使用Buffreader像磁盘写入数据时。当磁盘缓冲区未满时不会向里面写数据,所以用RandomAccessFill
* 实时写入,
* */
RandomAccessFile raf = new RandomAccessFile(file, "rw");
raf.setLength(size);
Runningthreadcount = threadcount;
for (int i = 0; i < threadcount; i++) {
long startIndex = i * blocksize;//开始位置
long endIndex = (i + 1) * blocksize;//结束位置
if (i == threadcount - 1) {
endIndex = size - 1;
}
//开启线程下载
new DownLoadThread(i, startIndex, path, endIndex,
fileName).start();
}
}
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
connection.disconnect();
}
}).start();
}
private static class DownLoadThread extends Thread {
private int threadId;
private long statrIndex;
private String path;
private long endIndex;
private String fileName;
public DownLoadThread(int threadId, long statrIndex, String path,
long endIndex, String fileName) {
super();
this.threadId = threadId;
this.statrIndex = statrIndex;
this.path = path;
this.endIndex = endIndex;
this.fileName = fileName;
}
public void run() {
try {
int total = 0;// 当前线程下载 大小
//把下载的了大小写入日志文件
File position = new File(
Environment.getExternalStorageDirectory(), threadId
+ ".log");// 日志文件
URL url = new URL(path);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setRequestMethod("GET");
//判断日志文件是否存在,得到下载大小
if (position.exists() && position.length() > 0) {
FileInputStream fis = new FileInputStream(position);
BufferedReader br = new BufferedReader(
new InputStreamReader(fis));
String lasttotalstr = br.readLine();
int lasttotal = Integer.valueOf(lasttotalstr);
System.out.println(threadId + " " + lasttotal);
statrIndex += lasttotal;
total += lasttotal;
fis.close();
br.close();
}
//从得到的断点继续下载
connection.setRequestProperty("Range", "bytes=" + statrIndex
+ "-" + endIndex);
connection.setConnectTimeout(10000);
connection.connect();
int code = connection.getResponseCode();
System.out.println(code);
InputStream stream = connection.getInputStream();
File file = new File(Environment.getExternalStorageDirectory(),
fileName);
RandomAccessFile raf = new RandomAccessFile(file, "rw");
raf.seek(statrIndex);
System.out.println(threadId + "线程写入地址" + statrIndex);
int len = 0;
byte[] buff = new byte[1024 * 1024];
while ((len = stream.read(buff)) != -1) {
RandomAccessFile rf = new RandomAccessFile(position, "rwd");
raf.write(buff, 0, len);
total += len;
rf.write(String.valueOf(total).getBytes());
rf.close();
}
stream.close();
raf.close();
System.out.println("end" + "wan" + threadId);
} catch (Exception e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} finally {
//处理线程安全问题
synchronized (downLoader.class) {
System.out.println("线程" + threadId + "下载完了");
Runningthreadcount = Runningthreadcount - 1;
System.out.println("Runningthreadcount"
+ Runningthreadcount);
System.out.println("下载完毕");
if (Runningthreadcount < 1) {
System.out.println("下载完毕");
for (int i = 0; i < threadcount; i++) {
File files = new File(
Environment.getExternalStorageDirectory(),
i + ".log");
files.delete();//下载完成后删除日志文件
}
}
}
}
}
}
}