多线程文件下载

多线程文件下载
</pre><pre name="code" class="java">import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.CountDownLatch;


public class FileDownLoader {

private static final int READ_TIMEOUT = 5 * 60 * 1000;
private static final int THREAD_COUNT = 2;

public FileDownLoader(String path, String savePath) {
super();
this.path = path;
this.savePath = savePath;
}


private String path; // 网络资源URL
private String savePath; // 下载后保存文件名


public void download() throws Exception {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(READ_TIMEOUT);

System.out.println(conn.getResponseCode() == 200 ? "连接成功" : "连接失败");

int filesize = conn.getContentLength();//得到文件大小
System.out.println("filesize:" + filesize);
conn.disconnect();


int blocksize = filesize / THREAD_COUNT + 1;

RandomAccessFile file = new RandomAccessFile(savePath, "rw");
file.setLength(filesize);//设置本地文件的大小
file.close();


   // 线程计数器 0:通行, >0:等待
CountDownLatch startSignal = new CountDownLatch(1); //所有线程开始信号,初始化值是1,默认等待
   CountDownLatch doneSignal = new CountDownLatch(THREAD_COUNT); //所有线程完成信号,初始化值是线程数,默认等待

for (int threadId = 1; threadId <= THREAD_COUNT ; threadId++) {
int startpos = (threadId - 1) * blocksize;//计算每条线程的下载位置
int endpos = threadId * blocksize -1;
if (threadId == THREAD_COUNT) {
endpos = filesize;
}
System.out.println("Thread-" + threadId + " is downloading " + startpos + "->" + endpos);
RandomAccessFile perthreadfile = new RandomAccessFile(savePath, "rw");//
perthreadfile.seek(startpos);//从文件的什么位置开始写入数据
new DownladerThread(threadId, path, startpos, endpos, perthreadfile, startSignal, doneSignal).start();
}

// 通知所有线程开始,1-1=0,放行
startSignal.countDown();
// 等待所有线程结束,子线程中实行-1操作,完成一个减去一个,所有都完成了,就变成0了,不在等待,继续执行下一行代码
doneSignal.await();
System.out.println("文件下载完成!");
}

private class DownladerThread extends Thread {


private int startpos; //从文件的什么位置开始下载
private int endpos; //下载到什么位置结束
private String path;
private RandomAccessFile file;
private int threadid;
   private CountDownLatch startSignal;
   private CountDownLatch doneSignal;

public DownladerThread(int threadid, String path, int startpos, int endpos, RandomAccessFile perthreadfile, 
CountDownLatch startSignal, CountDownLatch doneSignal) {
this.path = path;
this.startpos = startpos;
this.endpos = endpos;
this.file = perthreadfile;
this.threadid = threadid;
this.startSignal = startSignal;
this.doneSignal = doneSignal;
}

@Override
public void run() {
try {

// 等待开始信号,如果是0,放行
this.startSignal.await();

URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setReadTimeout(READ_TIMEOUT);
conn.setRequestProperty("Range", "bytes=" + this.startpos + "-" + this.endpos);

System.out.println("线程-" + threadid + " " +
((conn.getResponseCode() == 200 || conn.getResponseCode() == 206) ? "连接成功" : "连接失败"));

InputStream inStream = conn.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
while((len = inStream.read(buffer))!=-1){
file.write(buffer, 0, len);
}
file.close();
inStream.close();
System.out.println("线程-" + threadid + " " + "完成下载");

// 每结束一条线程信号量减一
this.doneSignal.countDown();

} catch (Exception e) {
e.printStackTrace();
}
}
}

public static void main(String[] args) throws Exception {
String path = "http://nb.baidupcs.com/file/83b68781234bbf8e441dfb61c0e01c39?bkt=p2-nb-815&fid=908029305-250528-526955738348260&time=1417078240&sign=FDTAXERLB-DCb740ccc5511e5e8fedcff06b081203-7NOHgl9ITcD3RHfUNtw2UHjjHQc%3D&to=nbb&fm=Nin,B,U,nc&newver=1&newfm=1&flow_ver=3&sl=81723458&expires=8h&rt=sh&r=156158280&mlogid=3273469455&vuk=908029305&vbdid=328837051&fin=2014-11-11%20235118.jpg&fn=2014-11-11%20235118.jpg";
String savePath = "d:/tt.jpg";
new FileDownLoader(path, savePath).download();
}


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值