多线程断点下载

  1. 多线程下载

     public class MultiThreadDownloader {
    
         private URL url;        // 目标地址
         private File file;        // 本地文件
         private long threadLen;    // 每个线程下载多少
    
         private static final int THREAD_AMOUNT = 3;                // 线程数
         private static final String DIR_PATH = "F:/Download";    // 下载目录
    
         public MultiThreadDownloader(String address) throws IOException {    
             // 记住下载地址
             url = new URL(address);                                                            
             // 截取地址中的文件名, 创建本地文件
             file = new File(DIR_PATH, address.substring(address.lastIndexOf("/") + 1));        
         }
    
         public void download() throws IOException {
             HttpURLConnection conn = (HttpURLConnection) url.openConnection();
             conn.setConnectTimeout(3000);
    
             // 获取文件总长度
             long totalLen = conn.getContentLength();                    
             // 计算每个线程要下载的长度
             // 总长度 如果能整除 线程数, 每条线程下载的长度就是 总长度 / 线程数
             // 总长度 如果不能整除 线程数, 那么每条线程下载长度就是 总长度 / 线程数 + 1
             threadLen = (totalLen + THREAD_AMOUNT - 1) / THREAD_AMOUNT;    
    
             // 在本地创建一个和服务端大小相同的文件
             RandomAccessFile raf = new RandomAccessFile(file, "rw");    
             // 设置文件的大小, 写入了若干个0
             raf.setLength(totalLen);                                    
             raf.close();
    
             // 按照线程数循环
             for (int i = 0; i < THREAD_AMOUNT; i++) {
                 // 开启线程, 每个线程将会下载一部分数据到本地文件中 
                 new DownloadThread(i).start();       
             }     
         }
    
         private class DownloadThread extends Thread {
             // 用来标记当前线程是下载任务中的第几个线程
             private int id;     
    
             public DownloadThread(int id) {
                 this.id = id;
             }
    
             public void run() {
                 // 从临时文件读取当前线程已完成的进度
    
                 long start = id * threadLen;     
                 long end = id * threadLen + threadLen - 1;
                 System.out.println("线程" + id + ": " + start + "-" + end);
    
                 try {
                     HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                     conn.setConnectTimeout(3000);
                     // 设置当前线程下载的范围(start和end都包含)
                     conn.setRequestProperty("Range", "bytes=" + start + "-" + end);    
    
                     InputStream in = conn.getInputStream();
                     // 随机读写文件, 用来向本地文件写出
                     RandomAccessFile raf = new RandomAccessFile(file, "rw");        
                     // 设置保存数据的位置
                     raf.seek(start);                                                
    
                     // 每次拷贝100KB
                     byte[] buffer = new byte[1024 * 100];    
                     int len;
                     while ((len = in.read(buffer)) != -1) {
                         // 从服务端读取数据, 写到本地文件
                         raf.write(buffer, 0, len);            
                     }
                     raf.close();
    
                     System.out.println("线程" + id + "下载完毕");
                 } catch (IOException e) {
                     e.printStackTrace();
                 }
             }
         }
    
         public static void main(String[] args) throws IOException {
             new MultiThreadDownloader("http://192.168.1.240:8080/14.Web/android-sdk_r17-windows.zip").download();
         }
     }
    
  2. 断点下载

     public class BreakpointDownloader {
         // 下载目录
         private static final String DIR_PATH = "F:/Download";    
         // 总线程数
         private static final int THREAD_AMOUNT = 3;                
    
         // 目标下载地址
         private URL url;            
         // 本地文件
         private File dataFile;        
         // 用来存储每个线程下载的进度的临时文件
         private File tempFile;        
         // 每个线程要下载的长度
         private long threadLen;      
         // 总共完成了多少  
         private long totalFinish;    
         // 服务端文件总长度
         private long totalLen;        
         // 用来记录开始下载时的时间
         private long begin;            
    
         public BreakpointDownloader(String address) throws IOException {    
             url = new URL(address);                                                            
             dataFile = new File(DIR_PATH, address.substring(address.lastIndexOf("/") + 1));    
             tempFile = new File(dataFile.getAbsolutePath() + ".temp");                        
         }
    
         public void download() throws IOException {
             HttpURLConnection conn = (HttpURLConnection) url.openConnection();
             conn.setConnectTimeout(3000);
    
             totalLen = conn.getContentLength();                                    
             threadLen = (totalLen + THREAD_AMOUNT - 1) / THREAD_AMOUNT;            
    
             if (!dataFile.exists()) {                                            
                 RandomAccessFile raf = new RandomAccessFile(dataFile, "rws");    
                 raf.setLength(totalLen);                                        
                 raf.close();
             }
    
             if (!tempFile.exists()) {                                            
                 RandomAccessFile raf = new RandomAccessFile(tempFile, "rws");    
                 for (int i = 0; i < THREAD_AMOUNT; i++)                           
                     raf.writeLong(0);                                            
                 raf.close();
             }
    
             for (int i = 0; i < THREAD_AMOUNT; i++) { 
                 new DownloadThread(i).start();       
             } 
    
             // 记录开始时间
             begin = System.currentTimeMillis();        
         }
    
         private class DownloadThread extends Thread {
             // 用来标记当前线程是下载任务中的第几个线程
             private int id;     
    
             public DownloadThread(int id) {
                 this.id = id;
             }
    
             public void run() {
                 try {
                     RandomAccessFile tempRaf = new RandomAccessFile(tempFile, "rws");        
                     tempRaf.seek(id * 8);                        
                     long threadFinish = tempRaf.readLong();        
                     synchronized(BreakpointDownloader.this) {    
                         totalFinish += threadFinish;            
                     }
    
                     long start = id * threadLen + threadFinish;      
                     long end = id * threadLen + threadLen - 1;       
                     System.out.println("线程" + id + ": " + start + "-" + end);
    
                     HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                     conn.setConnectTimeout(3000);
                     conn.setRequestProperty("Range", "bytes=" + start + "-" + end);        
    
                     InputStream in = conn.getInputStream();                              
                     RandomAccessFile dataRaf = new RandomAccessFile(dataFile, "rws");    
                     dataRaf.seek(start);                                                
    
                     byte[] buffer = new byte[1024 * 100];            
                     int len;
                     while ((len = in.read(buffer)) != -1) {
                         dataRaf.write(buffer, 0, len);               
                         threadFinish += len;                        
                         tempRaf.seek(id * 8);                        
                         tempRaf.writeLong(threadFinish);           
                         synchronized(BreakpointDownloader.this) {   
                             totalFinish += len;                        
                         }
                     }
                     dataRaf.close();
                     tempRaf.close();
    
                     System.out.println("线程" + id + "下载完毕");
                     // 如果已完成长度等于服务端文件长度(代表下载完成)
                     if (totalFinish == totalLen) {                    
                         System.out.println("下载完成, 耗时: " + (System.currentTimeMillis() - begin));
                         // 删除临时文件
                         tempFile.delete();                            
                     }
                 } catch (IOException e) {
                     e.printStackTrace();
                 }
             }
         }
    
         public static void main(String[] args) throws IOException {
             new BreakpointDownloader("http://192.168.1.240:8080/14.Web/android-sdk_r17-windows.zip").download();
         }
     }
    

results matching ""

    No results matching ""