zoukankan      html  css  js  c++  java
  • 多线程实现下载文件

    一:需求分析

    1:下载远程资源文件,通过多线程下载,达到高效的目的。

    2:使用5个线程分别下载文件的不同部分。

    二:定义成员变量以及初始化变量

     1 // 定义成员变量
     2     private String path; // 远程资源路径
     3     private String targetPath; // 本地存储路径
     4     private DownFileThread[] threads; // 线程list
     5     private int threadNum; // 线程数量
     6     private long length; // 下载的文件大小
     7 
     8     // 构造初始化
     9     public DownloadUtil(String path, String targetPath, int threadNum) {
    10         super();
    11         this.path = path;
    12         this.targetPath = targetPath;
    13         this.threads = new DownFileThread[threadNum];
    14         this.threadNum = threadNum;
    15     }

    三:多线程下载文件

     1 // 多线程下载文件资源
     2     public void download() {
     3         URL url;
     4         try {
     5             url = new URL(path);
     6             HttpURLConnection conn = (HttpURLConnection) url.openConnection();
     7             conn.setReadTimeout(5 * 1000); // 设置超时时间为5秒
     8             conn.setRequestMethod("GET");
     9             conn.setRequestProperty("connection", "keep-alive");
    10             conn.setRequestProperty("accept", "*/*");
    11 
    12             // 获取远程文件的大小
    13             length = conn.getContentLength();
    14             conn.disconnect();
    15 
    16             // 设置本地文件大小
    17             RandomAccessFile targetFile = new RandomAccessFile(targetPath, "rw");
    18             targetFile.setLength(length);
    19 
    20             // 每个线程下载大小
    21             long avgPart = length / threadNum + 1;
    22             // 下载文件
    23             for (int i = 0; i < threadNum; i++) {
    24                 long startPos = avgPart * i;
    25                 RandomAccessFile targetTmp = new RandomAccessFile(targetPath,
    26                         "rw");
    27                 targetTmp.seek(startPos); // 分段下载
    28                 threads[i] = new DownFileThread(startPos, targetTmp, avgPart);
    29                 threads[i].start();
    30             }
    31         } catch (Exception e) {
    32             e.printStackTrace();
    33         }
    34     }

    启动多个线程,每个线程下载文件的一部分,并发执行。

    四:监控文件下载进度

    1 // 监控下载进度
    2     public double getDownRate() {
    3         int currentSize = 0;
    4         for (int i = 0; i < threadNum; i++) {
    5             currentSize += threads[i].length;
    6         }
    7         return currentSize * 1.0 / length;
    8     }

    如果下载的文件比较大,可以使用进度条显示。

    五:定义线程类

     1 // 定义线程类
     2     class DownFileThread extends Thread {
     3         private long startPos;
     4         private RandomAccessFile raf;
     5         private long size;
     6         private long length;
     7 
     8         public DownFileThread(long startPos, RandomAccessFile raf, long size) {
     9             super();
    10             this.startPos = startPos;
    11             this.raf = raf;
    12             this.size = size;
    13         }
    14 
    15         public void run() {
    16             URL url;
    17             try {
    18                 url = new URL(path);
    19                 HttpURLConnection conn = (HttpURLConnection) url
    20                         .openConnection();
    21                 conn.setReadTimeout(5 * 1000); // 设置超时时间为5秒
    22                 conn.setRequestMethod("GET");
    23                 conn.setRequestProperty("connection", "keep-alive");
    24                 conn.setRequestProperty("accept", "*/*");
    25 
    26                 InputStream in = conn.getInputStream();
    27                 in.skip(this.startPos);
    28                 byte[] buf = new byte[1024];
    29                 int hasRead = 0;
    30                 while (length < size && (hasRead = in.read(buf)) != -1) {
    31                     raf.write(buf, 0, hasRead);
    32                     length += hasRead;
    33                 }
    34                 raf.close();
    35                 in.close();
    36             } catch (Exception e) {
    37                 e.printStackTrace();
    38             }
    39         }
    40     }

    六:测试多线程下载文件

     1 public static void main(String[] args) {
     2         String path = "http://localhost:8080/healthcare/html/HealthCare.war";
     3         String targetPath = "D:/healthcare.war";
     4         final DownloadUtil download = new DownloadUtil(path, targetPath, 4);
     5         download.download();
     6         // 主线程负责下载文件,在启动一个线程负责监控下载的进度
     7         new Thread(new Runnable() {
     8 
     9             @Override
    10             public void run() {
    11                 while (download.getDownRate() < 1) {
    12                     System.out.println(download.getDownRate());
    13                     try {
    14                         Thread.sleep(200); // 200毫秒扫描一次
    15                     } catch (InterruptedException e) {
    16                         e.printStackTrace();
    17                     }
    18                 }
    19             }
    20 
    21         }).start();
    22     }

    七:全部代码如下

      1 /**
      2  * 
      3  */
      4 package com.hlcui.thread;
      5 
      6 import java.io.InputStream;
      7 import java.io.RandomAccessFile;
      8 import java.net.HttpURLConnection;
      9 import java.net.URL;
     10 
     11 /**
     12  * @author Administrator 多线程下载文件
     13  */
     14 public class DownloadUtil {
     15     // 定义成员变量
     16     private String path; // 远程资源路径
     17     private String targetPath; // 本地存储路径
     18     private DownFileThread[] threads; // 线程list
     19     private int threadNum; // 线程数量
     20     private long length; // 下载的文件大小
     21 
     22     // 构造初始化
     23     public DownloadUtil(String path, String targetPath, int threadNum) {
     24         super();
     25         this.path = path;
     26         this.targetPath = targetPath;
     27         this.threads = new DownFileThread[threadNum];
     28         this.threadNum = threadNum;
     29     }
     30 
     31     // 多线程下载文件资源
     32     public void download() {
     33         URL url;
     34         try {
     35             url = new URL(path);
     36             HttpURLConnection conn = (HttpURLConnection) url.openConnection();
     37             conn.setReadTimeout(5 * 1000); // 设置超时时间为5秒
     38             conn.setRequestMethod("GET");
     39             conn.setRequestProperty("connection", "keep-alive");
     40             conn.setRequestProperty("accept", "*/*");
     41 
     42             // 获取远程文件的大小
     43             length = conn.getContentLength();
     44             conn.disconnect();
     45 
     46             // 设置本地文件大小
     47             RandomAccessFile targetFile = new RandomAccessFile(targetPath, "rw");
     48             targetFile.setLength(length);
     49 
     50             // 每个线程下载大小
     51             long avgPart = length / threadNum + 1;
     52             // 下载文件
     53             for (int i = 0; i < threadNum; i++) {
     54                 long startPos = avgPart * i;
     55                 RandomAccessFile targetTmp = new RandomAccessFile(targetPath,
     56                         "rw");
     57                 targetTmp.seek(startPos); // 分段下载
     58                 threads[i] = new DownFileThread(startPos, targetTmp, avgPart);
     59                 threads[i].start();
     60             }
     61         } catch (Exception e) {
     62             e.printStackTrace();
     63         }
     64     }
     65 
     66     // 监控下载进度
     67     public double getDownRate() {
     68         int currentSize = 0;
     69         for (int i = 0; i < threadNum; i++) {
     70             currentSize += threads[i].length;
     71         }
     72         return currentSize * 1.0 / length;
     73     }
     74 
     75     // 定义线程类
     76     class DownFileThread extends Thread {
     77         private long startPos;
     78         private RandomAccessFile raf;
     79         private long size;
     80         private long length;
     81 
     82         public DownFileThread(long startPos, RandomAccessFile raf, long size) {
     83             super();
     84             this.startPos = startPos;
     85             this.raf = raf;
     86             this.size = size;
     87         }
     88 
     89         public void run() {
     90             URL url;
     91             try {
     92                 url = new URL(path);
     93                 HttpURLConnection conn = (HttpURLConnection) url
     94                         .openConnection();
     95                 conn.setReadTimeout(5 * 1000); // 设置超时时间为5秒
     96                 conn.setRequestMethod("GET");
     97                 conn.setRequestProperty("connection", "keep-alive");
     98                 conn.setRequestProperty("accept", "*/*");
     99 
    100                 InputStream in = conn.getInputStream();
    101                 in.skip(this.startPos);
    102                 byte[] buf = new byte[1024];
    103                 int hasRead = 0;
    104                 while (length < size && (hasRead = in.read(buf)) != -1) {
    105                     raf.write(buf, 0, hasRead);
    106                     length += hasRead;
    107                 }
    108                 raf.close();
    109                 in.close();
    110             } catch (Exception e) {
    111                 e.printStackTrace();
    112             }
    113         }
    114     }
    115 
    116     // 测试
    117     public static void main(String[] args) {
    118         String path = "http://localhost:8080/healthcare/html/HealthCare.war";
    119         String targetPath = "D:/healthcare.war";
    120         final DownloadUtil download = new DownloadUtil(path, targetPath, 4);
    121         download.download();
    122         // 主线程负责下载文件,在启动一个线程负责监控下载的进度
    123         new Thread(new Runnable() {
    124 
    125             @Override
    126             public void run() {
    127                 while (download.getDownRate() < 1) {
    128                     System.out.println(download.getDownRate());
    129                     try {
    130                         Thread.sleep(200); // 200毫秒扫描一次
    131                     } catch (InterruptedException e) {
    132                         e.printStackTrace();
    133                     }
    134                 }
    135             }
    136 
    137         }).start();
    138     }
    139 }
    View Code

     

  • 相关阅读:
    Windows内核对象
    FreeWriting_1
    FreeWriting_2
    【整理】技术文章集锦
    【转】英语吵架一百句
    像 IDE 一样使用 vim
    统治世界的十大算法
    AnimationSet动画集合类的使用
    帮你解答adb是什么,adb有什么用
    SharedPreferences的简单使用
  • 原文地址:https://www.cnblogs.com/warrior4236/p/5686404.html
Copyright © 2011-2022 走看看