天天看點

java多線程檔案下載下傳_Java多線程檔案下載下傳

packagecom.test.service;importjava.io.File;importjava.io.InputStream;importjava.io.RandomAccessFile;importjava.net.HttpURLConnection;importjava.net.URL;importjava.util.concurrent.CountDownLatch;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.stereotype.Component;@Componentpublic classMulitThreadDownload {private static Logger logger = LoggerFactory.getLogger(MulitThreadDownload.class);

@Value("${onair.download.threadsize:5}")private int threadSize = 5;

@Value("${onair.download.timeout:5000}")private intdownloadTimeout;static boolean flag = true;//消息

private final CountDownLatch msgDownLatch = new CountDownLatch(1);//工作線程

private final CountDownLatch workDownLatch = newCountDownLatch(threadSize);private DowloadRunnable[] dowloadRunnables = newDowloadRunnable[threadSize];public static voidmain(String[] args) {new MulitThreadDownload().downloadFile("", "G:\\123.mp4");

}public booleandownloadFile(String url,String filePath){

logger.debug("下載下傳位址:{},目标檔案路徑:{}",url,filePath);try{

URL urlPath= newURL(url);

HttpURLConnection conn=(HttpURLConnection)urlPath.openConnection();

conn.setConnectTimeout(downloadTimeout);

conn.setRequestMethod("GET");int status =conn.getResponseCode();if(status == 200){ //200傳回所有,206傳回部分//檔案長度

int length =conn.getContentLength();

logger.info("擷取檔案大小:{}",length);//建立下載下傳檔案 指定大小

RandomAccessFile raf = new RandomAccessFile(new File(filePath), "rwd");

raf.setLength(length);

raf.close();//釋放資源//分塊大小

int blockSize = length /threadSize;//建立工作線程

for (int i = 1; i <= threadSize; i++) {int startIndex = blockSize*(i-1);int endIndex = blockSize * i - 1;if(i ==threadSize){

endIndex=length;

}

logger.info("線程:{}下載下傳檔案開始點:{}結束點:{}",i,startIndex,endIndex);

dowloadRunnables[i-1] = newDowloadRunnable(url,filePath,msgDownLatch, workDownLatch, i,startIndex,endIndex);

Thread thread= new Thread(dowloadRunnables[i-1]);

thread.start();

thread.setUncaughtExceptionHandler(newThread.UncaughtExceptionHandler() {

@Overridepublic voiduncaughtException(Thread t, Throwable e) {

logger.debug("catch到異常",e);

flag= false;

}

});

}//通知工作線程啟動,開始工作

msgDownLatch.countDown();

logger.debug("主線程阻塞,等待工作線程完成任務");//起一個線程監控下載下傳進度//moniterLength(length);//阻塞主線程,等待工作線程完成

workDownLatch.await();

logger.debug("工作線程完成任務,主線程繼續");returnflag;

}

}catch(Throwable e) {

logger.error("檔案下載下傳失敗:"+e.getMessage(),e);

File file= newFile(filePath);if(file.exists()){

file.delete();//下載下傳失敗 删除臨時檔案

}

}return false;

}//輸出下載下傳進度

private void moniterLength(intlength) {new Thread(newRunnable() {

@Overridepublic voidrun() {while(getDownloadLength()

logger.debug("檔案大小:{},目前下載下傳大小:{},進度{}",length,getDownloadLength(),getDownloadLength()* 1.0 / (long)length);try{

Thread.sleep(10000);

}catch(InterruptedException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}).start();

}//監控下載下傳進度

public intgetDownloadLength(){int length = 0;for (int i = 0; i < dowloadRunnables.length; i++) {

length+=dowloadRunnables[i].downloadLength;

}returnlength;

}

}//下載下傳線程

class DowloadRunnable implementsRunnable{private static Logger logger = LoggerFactory.getLogger(DowloadRunnable.class);privateCountDownLatch msgDownLatch;privateCountDownLatch workDownLatch;private intthreadIndex;private intstartIndex;private intendIndex;privateString url;privateString filePath;public int downloadLength; //已下載下傳大小

publicDowloadRunnable(String url, String filePath,

CountDownLatch msgDownLatch, CountDownLatch workDownLatch,int threadIndex, int startIndex, intendIndex) {this.url =url;this.filePath =filePath;this.msgDownLatch =msgDownLatch;this.workDownLatch =workDownLatch;this.threadIndex =threadIndex;this.startIndex =startIndex;this.endIndex =endIndex;

}

@Overridepublic voidrun() {try{//阻塞此線程,等待主線程給啟動消息(msgDownLatch.countDown());

msgDownLatch.await();//具體工作

logger.info("線程{}任務開始",threadIndex);

URL urlPath= newURL(url);

HttpURLConnection conn=(HttpURLConnection)urlPath.openConnection();

conn.setConnectTimeout(5000);

conn.setRequestProperty("Range", "bytes=" + startIndex + "-"

+endIndex);

conn.setRequestMethod("GET");int status =conn.getResponseCode();

logger.debug("線程{}請求傳回的responseCode:{}",threadIndex,status);if(status==206){

InputStream in=conn.getInputStream();

RandomAccessFile raf= new RandomAccessFile(filePath, "rwd");

raf.seek(startIndex);byte[] buffer = new byte[2048];int length = 0;

logger.debug("線程{}開始寫資料,開始點{}",threadIndex,startIndex);while((length = in.read(buffer)) != -1){//logger.debug("線程{}讀取大小:{}",threadIndex,length);

raf.write(buffer, 0, length);//downloadLength += length;

}

raf.close();

in.close();

}else{

logger.error("檔案下載下傳失敗,狀态碼:"+status);throw new Exception("檔案下載下傳失敗,狀态碼:"+status);

}

logger.info("線程{}任務完成",threadIndex);//工作完成

workDownLatch.countDown();

}catch(Throwable e) {

logger.error(e.getMessage(),e);

e.printStackTrace();

}

}

}