JAVA多執行緒下載的實現

明天還有我發表於2016-03-08

抽空研究的java多執行緒下載程式碼:

  1. package org.swinglife.download;  
  2.   
  3. import java.io.BufferedInputStream;  
  4. import java.io.BufferedOutputStream;  
  5. import java.io.File;  
  6. import java.io.FileOutputStream;  
  7. import java.io.IOException;  
  8. import java.io.InputStream;  
  9. import java.io.RandomAccessFile;  
  10. import java.net.HttpURLConnection;  
  11. import java.net.URL;  
  12.   
  13.   
  14. /*** 
  15.  * 2013.6.09 Download 
  16.  * @author swinglife 
  17.  *  
  18.  */  
  19. public class DownloadTest {  
  20.     private static final int THREADSIZE = 4;  
  21.     //下載路徑  
  22.     private static final String URL = "http://h.hiphotos.baidu.com/album/w%3D1366%3Bcrop%3D0%2C0%2C1366%2C768/sign=f263a79d91ef76c6d0d2ff28ab20c699/023b5bb5c9ea15ce216d95b5b7003af33b87b28e.jpg";  
  23.     //下載檔案  
  24.     private static final File TMP = new File("test.jpg");  
  25.       
  26.     public static void main(String[] args) throws Exception {  
  27.         URL url = new URL(URL);  
  28.         HttpURLConnection con = (HttpURLConnection) url.openConnection();  
  29.           
  30.         //獲得下載檔案大小  
  31.         int fileSize = con.getContentLength();  
  32.         createTmpFile(fileSize);  
  33.         //計算每個執行緒所要下載的位元組  
  34.         int dateSize = fileSize/THREADSIZE;  
  35.         //計算最後一段資料位元組  
  36.         int overSize = fileSize-dateSize*THREADSIZE;  
  37.         //剩餘位元組  
  38.         int endSize = 0;  
  39.         int startSize = 0;  
  40.           
  41.         //建立四個下載執行緒  
  42.         for (int i = 0; i < THREADSIZE; i++) {  
  43.             endSize = endSize + dateSize;  
  44.             startSize = endSize - dateSize;  
  45.             DownloadThread t = new DownloadThread(endSize, startSize, TMP,url);  
  46.             t.setName(String.valueOf(i)+"號執行緒"); //給執行緒設定名字  
  47.             t.start();  
  48.         }  
  49.           
  50.         System.out.println("最後一段資料位元組:"+overSize);  
  51.         overWriter(overSize, endSize, fileSize, url);  
  52.     }  
  53.       
  54.     /*** 
  55.      * 建立臨時檔案 
  56.      * @param fileSize 
  57.      * @throws Exception 
  58.      */  
  59.     private static void createTmpFile(int fileSize) throws Exception{  
  60.         byte[] buff = new byte[fileSize];  
  61.         //建立臨時檔案  
  62.         BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(TMP));  
  63.         out.write(buff, 0, buff.length);  
  64.         System.out.println("臨時檔案建立成功");  
  65.     }  
  66.       
  67.     /*** 
  68.      * 寫最後一段位元組資料 
  69.      * @param overSize 
  70.      * @param endSize 
  71.      * @param fileSize 
  72.      * @param url 
  73.      */  
  74.     private static void overWriter(int overSize,int endSize,int fileSize,URL url){  
  75.         //如果最後一段位元組還有那麼就寫完最後一點位元組  
  76.         if(overSize>0){  
  77.             System.out.println("開始寫最後一段資料");  
  78.             DownloadThread t = new DownloadThread(fileSize,endSize,TMP,url);  
  79.             t.setName("最後資料寫入執行緒");  
  80.             t.start();  
  81.         }  
  82.     }  
  83. }  
  84.   
  85. /*** 
  86.  * 下載執行緒類 
  87.  * @author swinglife 
  88.  * 
  89.  */  
  90. class DownloadThread extends Thread{  
  91.     private int endSize;    //結束位元組  
  92.     private int startSize;  //開始位元組  
  93.     private File file;  
  94.     private URL url;  
  95.   
  96.     public DownloadThread(int endSize,int startSize,File file,URL url){  
  97.         this.endSize = endSize;  
  98.         this.startSize = startSize;  
  99.         this.file = file;  
  100.         this.url = url;  
  101.     }  
  102.       
  103.     @Override  
  104.     public void run() {  
  105.         BufferedInputStream in = null;   
  106.         RandomAccessFile rf = null;  
  107.         try {  
  108.             System.out.println(super.getName()+"開始下載:"+startSize+"->"+endSize);  
  109.             in = new BufferedInputStream(openInputStream());  
  110.             rf = new RandomAccessFile(file, "rw");  
  111.             byte[] buff = new byte[1024];  
  112.             int length = 0;  
  113.             rf.seek(startSize); //跳到起始位元組  
  114.             while((length=in.read(buff, 0, buff.length))>0){  
  115.                 rf.write(buff,0,length);  
  116.             }  
  117.         } catch (IOException e) {  
  118.             e.printStackTrace();  
  119.         } finally{  
  120.             try {  
  121.                 in.close();  
  122.                 rf.close();  
  123.             } catch (IOException e) {  
  124.                 e.printStackTrace();  
  125.             }  
  126.         }  
  127.     }  
  128.       
  129.     /*** 
  130.      * 設定請求模式並返回輸入流 
  131.      * @return 
  132.      * @throws IOException 
  133.      */  
  134.     private InputStream openInputStream() throws IOException{  
  135.         HttpURLConnection con = (HttpURLConnection) url.openConnection();  
  136.         con.setRequestMethod("GET");  
  137.         //設定請求報頭屬性  
  138.         con.setRequestProperty("RANGE""bytes="+this.startSize+"-"+(this.endSize));  
  139.         System.out.println(con.getRequestProperty("RANGE"));  
  140.         return con.getInputStream();  
  141.     }  
  142. }  

相關文章