Java多线程下载文件

文件下载采用多线程方式能够充分利用CPU资源,关键点是设置线程的读取开始和结束位置。下面的代码,采用线程池启动10个线程来执行下载。

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class FileDownLoadTest {
	
	
	private static final int TCOUNT = 10;
	
	private CountDownLatch latch = new CountDownLatch(TCOUNT);

	private long completeLength = 0;
	
	private long fileLength;
	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		
		new FileDownLoadTest().download("http://localhost:8080/test/IESSAction.docx");
	}
	
	
	public void download(String address) throws Exception{
		ExecutorService service = Executors.newFixedThreadPool(TCOUNT);
		URL url = new URL(address);
		URLConnection cn = url.openConnection();
		cn.setRequestProperty("Referer", "http://www.test.com");
		fileLength = cn.getContentLength();
		long packageLength = fileLength/TCOUNT;
		long leftLength = fileLength%TCOUNT;
		RandomAccessFile file = new RandomAccessFile("d:\\test.docx","rw");
		//计算每个线程请求文件的开始和结束位置
		long pos = 0;
		long endPos = pos + packageLength;
		for(int i=0; i<TCOUNT; i++){
			if(leftLength >0){
				endPos ++;
				leftLength--;
			}
			service.execute(new DownLoadThread(url, file, pos, endPos));
			pos = endPos;
			endPos = pos + packageLength;
		}
		System.out.println("waiting........................................");
		long begin = System.currentTimeMillis();
		latch.await();
		file.close();
		System.out.println("end........................................");
		System.out.println(System.currentTimeMillis() - begin + "ms");
		service.shutdown();
	}
	
	class DownLoadThread implements Runnable{
		
		private URL url;
		private RandomAccessFile file;
		private long from;
		private long end;
		
		DownLoadThread(URL url, RandomAccessFile file, long from, long end){
			this.url = url;
			this.file = file;
			this.from = from;
			this.end = end;
		}
		
		
		public void run() {
			long pos = from;
			byte[] buf = new byte[512];
			try {
				HttpURLConnection cn = (HttpURLConnection) url.openConnection();
				cn.setRequestProperty("Range", "bytes=" + from + "-" + end);
				if(cn.getResponseCode() != 200 && cn.getResponseCode()!=206){
					run();
					return;
				}
				BufferedInputStream bis = new BufferedInputStream(cn.getInputStream());
				int len ;
				while((len = bis.read(buf)) != -1){
//					synchronized(file){
						file.seek(pos);
						file.write(buf, 0, len);
//					}
					pos += len;
					completeLength +=len;
					System.out.println("threadName: " + Thread.currentThread().getName() 
							+ "persent: " + completeLength * 100 /fileLength + "%");
				}
				cn.disconnect();
				latch.countDown();
			} catch (IOException e) {
				e.printStackTrace();
				
			}
		}
	}
}



 


 

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值