抽空研究的java多线程下载代码:
package org.swinglife.download;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
/***
* 2013.6.09 Download
* @author swinglife
*
*/
public class DownloadTest {
private static final int THREADSIZE = 4;
//下载路径
private static final String URL = "http://h.hiphotos.baidu.com/album/w%3D1366%3Bcrop%3D0%2C0%2C1366%2C768/sign=f263a79d91ef76c6d0d2ff28ab20c699/023b5bb5c9ea15ce216d95b5b7003af33b87b28e.jpg";
//下载文件
private static final File TMP = new File("test.jpg");
public static void main(String[] args) throws Exception {
URL url = new URL(URL);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
//获得下载文件大小
int fileSize = con.getContentLength();
createTmpFile(fileSize);
//计算每个线程所要下载的字节
int dateSize = fileSize/THREADSIZE;
//计算最后一段数据字节
int overSize = fileSize-dateSize*THREADSIZE;
//剩余字节
int endSize = 0;
int startSize = 0;
//创建四个下载线程
for (int i = 0; i < THREADSIZE; i++) {
endSize = endSize + dateSize;
startSize = endSize - dateSize;
DownloadThread t = new DownloadThread(endSize, startSize, TMP,url);
t.setName(String.valueOf(i)+"号线程"); //给线程设置名字
t.start();
}
System.out.println("最后一段数据字节:"+overSize);
overWriter(overSize, endSize, fileSize, url);
}
/***
* 创建临时文件
* @param fileSize
* @throws Exception
*/
private static void createTmpFile(int fileSize) throws Exception{
byte[] buff = new byte[fileSize];
//创建临时文件
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(TMP));
out.write(buff, 0, buff.length);
System.out.println("临时文件创建成功");
}
/***
* 写最后一段字节数据
* @param overSize
* @param endSize
* @param fileSize
* @param url
*/
private static void overWriter(int overSize,int endSize,int fileSize,URL url){
//如果最后一段字节还有那么就写完最后一点字节
if(overSize>0){
System.out.println("开始写最后一段数据");
DownloadThread t = new DownloadThread(fileSize,endSize,TMP,url);
t.setName("最后数据写入线程");
t.start();
}
}
}
/***
* 下载线程类
* @author swinglife
*
*/
class DownloadThread extends Thread{
private int endSize; //结束字节
private int startSize; //开始字节
private File file;
private URL url;
public DownloadThread(int endSize,int startSize,File file,URL url){
this.endSize = endSize;
this.startSize = startSize;
this.file = file;
this.url = url;
}
@Override
public void run() {
BufferedInputStream in = null;
RandomAccessFile rf = null;
try {
System.out.println(super.getName()+"开始下载:"+startSize+"->"+endSize);
in = new BufferedInputStream(openInputStream());
rf = new RandomAccessFile(file, "rw");
byte[] buff = new byte[1024];
int length = 0;
rf.seek(startSize); //跳到起始字节
while((length=in.read(buff, 0, buff.length))>0){
rf.write(buff,0,length);
}
} catch (IOException e) {
e.printStackTrace();
} finally{
try {
in.close();
rf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/***
* 设置请求模式并返回输入流
* @return
* @throws IOException
*/
private InputStream openInputStream() throws IOException{
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
//设置请求报头属性
con.setRequestProperty("RANGE", "bytes="+this.startSize+"-"+(this.endSize));
System.out.println(con.getRequestProperty("RANGE"));
return con.getInputStream();
}
}