java 多线程下载文件并实时计算下载百分比(断点续传)
生活随笔
收集整理的這篇文章主要介紹了
java 多线程下载文件并实时计算下载百分比(断点续传)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
多線程下載文件
多線程同時下載文件即:在同一時間內通過多個線程對同一個請求地址發起多個請求,將需要下載的數據分割成多個部分,同時下載,每個線程只負責下載其中的一部分,最后將每一個線程下載的部分組裝起來即可。
涉及的知識及問題
- 請求的數據怎么拆分
- 拆分完成后怎么下載
- 如何計算實時下載量
一.請求的數據怎么拆分
1 int blockSize =fileLength/threadCount; //計算每個線程需要下的長度 2 for(int i=0;i<threadCount;i++) { 3 int startSize=i*blockSize; //當前線程需要下載的開始位置 4 int endSize=(i+1)*blockSize-1;//當前線程需要下載的結束位置 5 if(1+i==threadCount) { //最后一個線程的結尾賦值文件大小 6 endSize=fileLength; 7 } 8 threadList[i]= new DownThread_1(filePath, fileUrl, "線程"+i, startSize, endSize); 9 threadList[i].start(); 10 } 11二.拆分完成后怎么下載
try {URL url = new URL(urlPath);HttpURLConnection coon = (HttpURLConnection) url.openConnection();coon.setRequestProperty("range","bytes="+startSize+"-"+endSize); //設置獲取下載資源的開始位置和結束位置coon.setConnectTimeout(5000);if(coon.getResponseCode()==206) {//響應碼 因為上面設置了range 所有響應碼是206不再是200BufferedInputStream bi=new BufferedInputStream(coon.getInputStream());RandomAccessFile raf=new RandomAccessFile(filePath, "rwd"); //斷點續傳的關鍵raf.seek(startSize); //將寫入點移動到當前線程寫入開始位置byte b[]=new byte[1024];int len=0;while ((len=bi.read(b))>-1) { //循環寫入raf.write(b, 0, len);synchronized (DownUtile.class) {//此處涉及到變量同步DownUtile.downLength=DownUtile.downLength+len; //計算當前下載了多少 }}raf.close();bi.close();System.out.println("thread"+threadName+"下載完成,開始位置"+startSize+",結束位置"+endSize);}} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}三.如何計算實時下載量
while ((len=bi.read(b))>-1) { //循環寫入raf.write(b, 0, len);synchronized (DownUtile.class) {//此處涉及到變量同步DownUtile.downLength=DownUtile.downLength+len; //計算當前下載了多少 }}while(DownUtile.downOver) {Thread.sleep(500); //間隔0.5秒計算一下if(DownUtile.downLength==fileLength) {DownUtile.downOver=false;System.out.println("下載完成:100%");}else {System.out.println("已經下載了:"+((int) (float)DownUtile.downLength / (float) fileLength * 100)+"%");}}上述方法中? 用到了synchronized(類鎖),為什么用到類鎖,因為計算下載的參數在DownUtile類中,為了保證這個參數在多線程中同步,需保證在執行累加操作時線程安全。
?
下面貼上全部的代碼
1 public class DownLoadUtile { 2 public static String filePath="C:\\Users\\Administrator\\Desktop\\下載\\ deme.exe"; //文件保存地址 3 public static String fileUrl="http://123.6.39.120/dlied1.qq.com/lol/dltools/LOL_V4.1.2.3-V4.1.2.4_PATCH_0_tgod_signed.exe?mkey=5cfc8d87dddd9a57&f=5844&cip=221.221.188.162&proto=http";//文件地址 4 public static int threadCount=5; //線程數量 5 public static int fileLength=0; //文件大小 6 public static Thread [] threadList=new Thread[threadCount]; 7 8 public DownLoadUtile() { 9 10 } 11 public DownLoadUtile(int threadCount) {//有參構造 12 this.threadCount=threadCount; 13 } 14 15 public static void main(String[] args) throws Exception { 16 URL url=new URL(fileUrl); 17 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //創建連接對象 18 conn.setConnectTimeout(5000);//請求超時時間 19 20 int code = conn.getResponseCode(); 21 System.out.println("服務器響應碼"+code); 22 if(code==200) {//響應正常 23 fileLength=conn.getContentLength(); //獲取文件大小 24 File file = new File(filePath); 25 if(!file.exists()) { 26 file.createNewFile(); 27 } 28 RandomAccessFile raf = new RandomAccessFile(filePath, "rwd"); //斷點續傳的關鍵 29 raf.setLength(fileLength); 30 31 int blockSize =fileLength/threadCount; //計算每個線程需要下的長度 32 for(int i=0;i<threadCount;i++) { 33 int startSize=i*blockSize; //當前線程需要下載的開始位置 34 int endSize=(i+1)*blockSize-1;//當前線程需要下載的結束位置 35 if(1+i==threadCount) { //最后一個線程的結尾賦值文件大小 36 endSize=fileLength; 37 } 38 threadList[i]= new DownThread_1(filePath, fileUrl, "線程"+i, startSize, endSize); 39 threadList[i].start(); 40 } 41 42 while(DownUtile.downOver) { 43 Thread.sleep(500); //間隔0.5秒計算一下 44 if(DownUtile.downLength==fileLength) { 45 DownUtile.downOver=false; 46 System.out.println("下載完成:100%"); 47 }else { 48 System.out.println("已經下載了:"+((int) (float)DownUtile.downLength / (float) fileLength * 100)+"%"); 49 } 50 } 51 52 }else { 53 System.out.println("服務器響應失敗"+code); 54 } 55 56 }?
下載類
1 public class DownThread_1 extends Thread{ 2 3 private String filePath; 4 private String urlPath; 5 private String threadName; 6 private int startSize; 7 private int endSize; 8 9 public DownThread_1(String filePath,String urlPath,String threadName,int startSize,int endSize) { 10 this.endSize=endSize; 11 this.startSize=startSize; 12 this.filePath=filePath; 13 this.urlPath=urlPath; 14 this.threadName=threadName; 15 } 16 @Override 17 public void run() { 18 try { 19 URL url = new URL(urlPath); 20 HttpURLConnection coon = (HttpURLConnection) url.openConnection(); 21 coon.setRequestProperty("range","bytes="+startSize+"-"+endSize); //設置獲取下載資源的開始位置和結束位置 22 coon.setConnectTimeout(5000); 23 if(coon.getResponseCode()==206) {//響應碼 因為上面設置了range 所有響應碼是206不再是200 24 BufferedInputStream bi=new BufferedInputStream(coon.getInputStream()); 25 RandomAccessFile raf=new RandomAccessFile(filePath, "rwd"); //斷點續傳的關鍵 26 raf.seek(startSize); //將寫入點移動到當前線程寫入開始位置 27 byte b[]=new byte[1024]; 28 int len=0; 29 while ((len=bi.read(b))>-1) { //循環寫入 30 raf.write(b, 0, len); 31 synchronized (DownUtile.class) {//此處涉及到變量同步 32 DownUtile.downLength=DownUtile.downLength+len; //計算當前下載了多少 33 } 34 } 35 raf.close(); 36 bi.close(); 37 System.out.println("thread"+threadName+"下載完成,開始位置"+startSize+",結束位置"+endSize); 38 } 39 } catch (MalformedURLException e) { 40 e.printStackTrace(); 41 } catch (IOException e) { 42 e.printStackTrace(); 43 } 44 } 45 46 }參數類
1 public class DownUtile { 2 3 public static int downLength=0;//已經下載了多少 4 5 public static boolean downOver=true; //下載是否完成 6 7 }?
轉載于:https://www.cnblogs.com/codebj/p/10994490.html
總結
以上是生活随笔為你收集整理的java 多线程下载文件并实时计算下载百分比(断点续传)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java中 ArrayList类常用方法
- 下一篇: spring框架学习1:搭建测试