使用多线程下载文件可以更快完成文件的下载,多线程下载文件之所以快,是因为其抢占的服务器资源多。如:假设服务器同时最多服务100个用户,在服务器中一条线程对应一个用户,100条线程在计算机中并非并发执行,而是由CPU划分时间片轮流执行,如果A应用使用了99条线程下载文件,那么相当于占用了99个用户的资源,假设一秒内CPU分配给每条线程的平均执行时间是10ms,A应用在服务器中一秒内就得到了990ms的执行时间,而其他应用在一秒内只有10ms的执行时间。就如同一个水龙头,每秒出水量相等的情况下,放990毫秒的水肯定比放10毫秒的水要多。

 

  1. XML/HTML 代码复制内容到剪贴板  
  2.       
  3. package cn.mzba.download;        
  4.         
  5. import java.io.File;        
  6. import java.io.InputStream;        
  7. import java.io.RandomAccessFile;        
  8. import java.net.HttpURLConnection;        
  9. import java.net.URL;        
  10.         
  11. public class MulThreadDownloader {        
  12.         
  13.     /**        
  14.      * 1、首先获取网络上的内容,然后获取文件的长度,标题。 然后在本地上生成一个同样大小并且同名的文件。 2、执行线程        
  15.      * 3、线程首先定义一个随机输入流,用来下载文件同步写入本地文件 设置Range从指定的开始位置-结束位置下载文件。        
  16.      * 4、获取服务器返回的输入流写入文件。        
  17.      *         
  18.      */        
  19.     public static void main(String[] args) throws Exception {        
  20.         String path = "http://www.wo...56c.jpg";        
  21.         new MulThreadDownloader().download(path, 3);        
  22.         System.in.read();        
  23.     }        
  24.         
  25.     public void download(String path, int threadsize) throws Exception {        
  26.         URL url = new URL(path);        
  27.         HttpURLConnection conn = (HttpURLConnection) url.openConnection();        
  28.         conn.setRequestMethod("GET");        
  29.         conn.setConnectTimeout(5 * 1000);        
  30.         int length = conn.getContentLength(); // 获取文件长度        
  31.         File localfile = new File(getFileName(path));        
  32.         RandomAccessFile file = new RandomAccessFile(localfile, "rwd");        
  33.         file.setLength(length);        
  34.         file.close();        
  35.         // 计算每条线程下载的数据长度        
  36.         int block = length % threadsize == 0 ? length / threadsize : length        
  37.                 / threadsize + 1;        
  38.         for (int i = 0; i < threadsize; i++) {        
  39.             new DownLoadThread(i, url, block, localfile).start();        
  40.         }        
  41.     }        
  42.         
  43.     private final class DownLoadThread extends Thread {        
  44.         
  45.         private int threadid;        
  46.         private URL url;        
  47.         private int block;        
  48.         private File localfile;        
  49.         
  50.         public DownLoadThread(int threadid, URL url, int block, File localfile) {        
  51.             this.threadid = threadid;        
  52.             this.block = block;        
  53.             this.url = url;        
  54.             this.localfile = localfile;        
  55.         }        
  56.         
  57.         @Override        
  58.         public void run() {        
  59.             int startposition = threadid * block; // 从网络文件的什么位置开始下载数据        
  60.             int endposition = startposition + block - 1; // 下载到文件的什么位置结束        
  61.             RandomAccessFile file;        
  62.             try {        
  63.                 file = new RandomAccessFile(localfile, "rwd");        
  64.                 file.seek(startposition);        
  65.                 HttpURLConnection conn = (HttpURLConnection) url        
  66.                         .openConnection();        
  67.                 conn.setRequestMethod("GET");        
  68.                 conn.setConnectTimeout(5 * 1000);        
  69.                 conn.setRequestProperty("Range", "bytes=" + startposition + "-"        
  70.                         + endposition);        
  71.                 InputStream is = conn.getInputStream();        
  72.                 byte[] buffer = new byte[1024];        
  73.                 int len = 0;        
  74.                 while ((len = is.read(buffer)) != -1) {        
  75.                     file.write(buffer, 0, len);        
  76.                 }        
  77.                 is.close();        
  78.                 file.close();        
  79.                 System.out.println("线程id" + threadid + "已经下载完成");        
  80.             } catch (Exception e) {        
  81.                 // TODO Auto-generated catch block        
  82.                 e.printStackTrace();        
  83.             }        
  84.         
  85.             super.run();        
  86.         }        
  87.         
  88.     }        
  89.         
  90.     public static String getFileName(String path) {        
  91.         return path.substring(path.lastIndexOf("/") + 1);        
  92.     }        
  93. }