zoukankan      html  css  js  c++  java
  • Android多线程下载

    一、多线程下载的原理、

          

          将服务端的资源划分给成几个等分的块,分配给不同的线程同时执行下载。

          划分方法 :

                      每个线程分配的长度为:int blocksize = length/n    

                      每个线程的起止位置(i-1)*blocksize--->i*blocksize-1        

                      最后一个线程结束位置为length

    二、步骤:

           1、在客户端创建与服务端同等大小的文件,使用RandomAccessFile类远程文件的设置操作

           2.、开启几个线程,分配下载资源

           3.、所有的线程执行完毕之后,文件下载完毕

    三、java实现的多线程下载

      1 package com.lewu.download;
      2 
      3 import java.io.File;
      4 import java.io.FileInputStream;
      5 import java.io.FileOutputStream;
      6 import java.io.InputStream;
      7 import java.io.RandomAccessFile;
      8 import java.net.HttpURLConnection;
      9 import java.net.URL;
     10 
     11 public class DownloadTest {
     12     public static final String path = "http://192.168.1.118:8080/web/youdao.exe";
     13     public static int threadcount = 0;
     14 
     15     public static void main(String[] args) throws Exception {
     16         // 1.在客户端端创建一个相同大小的文件(获取服务器文件的大小)
     17 
     18         URL url = new URL(path);
     19         HttpURLConnection conn = (HttpURLConnection) url.openConnection();
     20         conn.setRequestMethod("GET");
     21         conn.setConnectTimeout(5000);
     22         conn.setRequestProperty(
     23                 "User-Agent",
     24                 "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727)");
     25         int length = conn.getContentLength();
     26         System.err.println("文件的长度为"+length);
     27         File file = new File("youdao.exe");
     28         RandomAccessFile randomfile = new RandomAccessFile(file, "rwd");
     29         randomfile.setLength(length);
     30 
     31         // 创建三个线程 :线程分配下载资源
     32         int blocksize = length / 3;
     33         for (int i = 1; i <=3; i++) {
     34             // 线程执行下载操作 ,需要定位下载的位置,则需要设置一些参数
     35             int beginsize = (i - 1) * blocksize;
     36             int endsize = i * blocksize - 1;
     37             if (i == 3) {
     38                 endsize = length;
     39             }
     40             int id = i;
     41 
     42             // 启动线程
     43             new Thread(new DownloadThread(id, beginsize, endsize)).start();
     44         }
     45 
     46     }
     47 
     48     static class DownloadThread implements Runnable {
     49 
     50         private int id;
     51         private int beginsize;
     52         private int endsize;
     53 
     54         public DownloadThread(int id, int beginsize, int endsize) {
     55             this.id = id;
     56             this.beginsize = beginsize;
     57             this.endsize = endsize;
     58         }
     59 
     60         @Override
     61         public void run() {
     62             try {
     63                 // 每一个线程在创建的时候 都创建一个名为id.text的文件用来保存下载进度
     64                 File idfile = new File("" + id + ".txt");
     65                 if (idfile.exists()) {
     66                     // 将内容即进度读取出来
     67                     FileInputStream fin = new FileInputStream(idfile);
     68                     byte[] result = StreamTools.getBytes(fin);
     69                     String strinfo = new String(result);
     70                     if (!"".equals(strinfo) && strinfo != null) {
     71                         beginsize = Integer.parseInt(strinfo);
     72                     }
     73                 }
     74                 URL url = new URL(DownloadTest.path);
     75                 HttpURLConnection conn = (HttpURLConnection) url
     76                         .openConnection();
     77 
     78                 conn.setRequestMethod("GET");
     79                 conn.setConnectTimeout(5000);
     80                 if (beginsize > endsize) {
     81                     beginsize = endsize - 1;
     82                 }
     83                 conn.setRequestProperty(
     84                         "User-Agent",
     85                         "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727)");
     86                 conn.setRequestProperty("Range", "bytes=" + beginsize + "-"
     87                         + endsize);
     88                 System.out.println("线程"+id+"从" + beginsize + "开始下载" + endsize + "结束");
     89 
     90                 File file = new File("youdao.exe");
     91                 RandomAccessFile randomfile = new RandomAccessFile(file, "rwd");
     92                 // 如果下载被强行中断,这保存下载的位置,
     93                 randomfile.seek(beginsize);
     94 
     95                 InputStream in = conn.getInputStream();
     96                 byte[] bt = new byte[1024];
     97 
     98                 int len = 0;
     99                 int total = 0;
    100                 while ((len = in.read(bt)) != -1) {
    101                     randomfile.write(bt, 0, len);
    102                     // 下载量 下载位置
    103                     total += len;
    104                     // 将位置信息保存到相应的文件
    105                     FileOutputStream out = new FileOutputStream(idfile);
    106                     out.write((beginsize + total + "").getBytes());
    107                     out.flush();
    108                     out.close();
    109 
    110                 }
    111                 in.close();
    112                 randomfile.close();
    113                 System.out.println("线程" + id + "执行完毕!");
    114 
    115                 // 使用synchronized的代码块保count被多个线程同时访问
    116                 synchronized (DownloadTest.class) {
    117                     DownloadTest.threadcount++;
    118                     if (DownloadTest.threadcount >= 3) {
    119                         System.out.println("所有的线程都执行完毕了");
    120                         for (int i = 0; i < 3; i++) {
    121                             File deleteFile = new File(i + ".txt");
    122                             System.out.println(i + "删除" + deleteFile.delete());
    123                         }
    124                     }
    125 
    126                 }
    127 
    128             } catch (Exception e) {
    129                 e.printStackTrace();
    130             }
    131         }
    132     }
    133 }

     四、移植到Android上

           功能:1、界面上有下载进度条,可以记录下载进度

                   2、设置暂停按钮(通过设置flag控制)

      1 package com.lewu.download;
      2 
      3 import java.io.File;
      4 import java.io.FileInputStream;
      5 import java.io.FileOutputStream;
      6 import java.io.InputStream;
      7 import java.io.RandomAccessFile;
      8 import java.net.HttpURLConnection;
      9 import java.net.URL;
     10 import android.app.Activity;
     11 import android.os.Bundle;
     12 import android.os.Environment;
     13 import android.view.View;
     14 import android.view.View.OnClickListener;
     15 import android.widget.Button;
     16 import android.widget.EditText;
     17 import android.widget.ProgressBar;
     18 import android.widget.Toast;
     19 
     20 public class MutiDownloadAndActivity extends Activity implements
     21         OnClickListener {
     22     private EditText down_edit;
     23     private Button down_sure;
     24     private Button down_stop;
     25     private ProgressBar bar;
     26     private int totalsize;
     27     private boolean flag=true;
     28     public static int threadcount = 0;
     29 
     30     @Override
     31     public void onCreate(Bundle savedInstanceState) {
     32         super.onCreate(savedInstanceState);
     33         setContentView(R.layout.main);
     34 
     35         down_edit = (EditText) findViewById(R.id.down_edit);
     36         down_sure = (Button) findViewById(R.id.down_sure);
     37         down_stop = (Button) findViewById(R.id.down_stop);
     38         bar = (ProgressBar) findViewById(R.id.progressBar1);
     39 
     40         down_sure.setOnClickListener(this);
     41         down_stop.setOnClickListener(this);
     42 
     43     }
     44 
     45     @Override
     46     public void onClick(View v) {
     47         switch (v.getId()) {
     48         case R.id.down_sure:
     49 
     50             String path = down_edit.getText().toString().trim();
     51             System.out.println(path + ">>>>>>>>>>");
     52             if ("".equals(path)) {
     53                 Toast.makeText(this, "路径不能为空", 0);
     54                 return;
     55             } else {
     56                 down_stop.setClickable(true);
     57                 down_stop.setEnabled(true);
     58                 try {
     59                     URL url = new URL(path);
     60                     HttpURLConnection conn = (HttpURLConnection) url
     61                             .openConnection();
     62                     conn.setRequestMethod("GET");
     63                     conn.setConnectTimeout(5000);
     64                     conn.setRequestProperty(
     65                             "User-Agent",
     66                             "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727)");
     67                     int length = conn.getContentLength();
     68                     System.err.println("文件的长度为" + length);
     69                     //设置进度条的进度
     70                     bar.setMax(length);
     71                     File file = new File(
     72                             Environment.getExternalStorageDirectory(),
     73                             getFileName(path));
     74                     RandomAccessFile randomfile = new RandomAccessFile(file,
     75                             "rwd");
     76                     randomfile.setLength(length);
     77 
     78                     // 创建三个线程 :线程分配下载资源
     79                     int blocksize = length / 3;
     80                     for (int i = 1; i <= 3; i++) {
     81                         // 线程执行下载操作 ,需要定位下载的位置,则需要设置一些参数
     82                         int beginsize = (i - 1) * blocksize;
     83                         int endsize = i * blocksize - 1;
     84                         if (i == 3) {
     85                             endsize = length;
     86                         }
     87                         int id = i;
     88 
     89                         // 启动线程
     90                         new Thread(new DownloadThread(id, beginsize, endsize,
     91                                 path)).start();
     92 
     93                     }
     94                 } catch (Exception e) {
     95                     e.printStackTrace();
     96                 }
     97                 break;
     98             }
     99 
    100         case R.id.down_stop:
    101             flag = false;
    102             down_stop.setClickable(true);
    103             down_stop.setEnabled(true);
    104 
    105             break;
    106 
    107         }
    108     }
    109 
    110     class DownloadThread implements Runnable {
    111 
    112         private int id;
    113         private int beginsize;
    114         private int endsize;
    115         private String path;
    116 
    117         public DownloadThread(int id, int beginsize, int endsize, String path) {
    118             this.id = id;
    119             this.beginsize = beginsize;
    120             this.endsize = endsize;
    121             this.path = path;
    122         }
    123 
    124         @Override
    125         public void run() {
    126             try {
    127                 flag = true;
    128                 // 每一个线程在创建的时候 都创建一个名为id.text的文件用来保存下载进度
    129                 File idfile = new File("/mnt/sdcard/" + id + ".txt");
    130                 if (idfile.exists()) {
    131                     // 将内容即进度读取出来
    132                     FileInputStream fin = new FileInputStream(idfile);
    133                     byte[] result = StreamTools.getBytes(fin);
    134                     String strinfo = new String(result);
    135                     if (!"".equals(strinfo) && strinfo != null) {
    136                         beginsize = Integer.parseInt(strinfo);
    137                     }
    138                 }
    139                 URL url = new URL(path);
    140                 HttpURLConnection conn = (HttpURLConnection) url
    141                         .openConnection();
    142 
    143                 conn.setRequestMethod("GET");
    144                 conn.setConnectTimeout(5000);
    145                 if (beginsize > endsize) {
    146                     beginsize = endsize - 1;
    147                 }
    148                 conn.setRequestProperty(
    149                         "User-Agent",
    150                         "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727)");
    151                 conn.setRequestProperty("Range", "bytes=" + beginsize + "-"
    152                         + endsize);
    153                 System.out.println("线程" + id + "从" + beginsize + "开始下载"
    154                         + endsize + "结束");
    155 
    156                 File file = new File(Environment.getExternalStorageDirectory(),
    157                         getFileName(path));
    158                 RandomAccessFile randomfile = new RandomAccessFile(file, "rwd");
    159                 // 如果下载被强行中断,这保存下载的位置,
    160                 randomfile.seek(beginsize);
    161 
    162                 InputStream in = conn.getInputStream();
    163                 byte[] bt = new byte[1024];
    164 
    165                 int len = 0;
    166                 int total = 0;
    167                 while ((len = in.read(bt)) != -1) {
    168                     randomfile.write(bt, 0, len);
    169                     // 下载量 下载位置
    170                     total += len;
    171 
    172                     // 设置进度条的进度
    173                     setProgressbarProgress(len);
    174 
    175                     // 将位置信息保存到相应的文件
    176                     FileOutputStream out = new FileOutputStream(idfile);
    177                     out.write((beginsize + total + "").getBytes());
    178                     out.flush();
    179                     out.close();
    180                     if(!flag){
    181                         return;
    182                     }
    183 
    184                 }
    185                 in.close();
    186                 randomfile.close();
    187                 System.out.println("线程" + id + "执行完毕!");
    188 
    189                 // 使用synchronized的代码块保count被多个线程同时访问
    190                 synchronized (MutiDownloadAndActivity.class) {
    191                     MutiDownloadAndActivity.threadcount++;
    192                     if (MutiDownloadAndActivity.threadcount >= 3) {
    193                         System.out.println("所有的线程都执行完毕了");
    194                         for (int i = 1; i <= 3; i++) {
    195                             File deleteFile = new File("/mnt/sdcard/" + i
    196                                     + ".txt");
    197                             System.out.println(i + "删除" + deleteFile.delete());
    198                         }
    199                     }
    200 
    201                 }
    202 
    203             } catch (Exception e) {
    204                 e.printStackTrace();
    205             }
    206         }
    207     }
    208 
    209     public static String getFileName(String path) {
    210         int index = path.lastIndexOf("/") + 1;
    211         return path.substring(index);
    212 
    213     }
    214 
    215     public void setProgressbarProgress(int len) {
    216         if (len != 0) {
    217             totalsize += len;
    218             bar.setProgress(totalsize);
    219         }
    220 
    221     }
    222 
    223 }

          下载界面:

         

  • 相关阅读:
    HDU 4536 XCOM Enemy Unknown ( 状态压缩+搜索)
    HDU 4535 吉哥系列故事——礼尚往来(水题,错排)
    HDU 4541 Ten Googol
    HDU 4544 湫湫系列故事——消灭兔子 (优先队列)
    HDU 4530 小Q系列故事——大笨钟(水题)
    HDU 4505 小Q系列故事——电梯里的爱情 (水题)
    HDU 2197 本原串 (数学)
    HDU 4540 威威猫系列故事——打地鼠 (简单DP)
    oracle数据库恢复
    编程中的命名设计那点事(转)
  • 原文地址:https://www.cnblogs.com/tagie/p/3074966.html
Copyright © 2011-2022 走看看