您的位置:首页 > 移动开发 > Android开发

Android多线程下载

2014-01-14 11:05 344 查看

一、多线程下载的原理、



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

划分方法 :

每个线程分配的长度为: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 }


下载界面:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: