多线程下载在我们生活中非常常见,比如迅雷就是我们常用的多线程的下载工具,当然还有断点续传,断点续传我们在下一节来讲,android手机端下载文件时也可以用多线程下载,我们这里是在java中写一个测试,其实android中的实现和java是一样的,学会了java就知道怎么在android中实现了,废话不多说了,怎么实现多线程和多线程的原理是什么样的,现在我们来学习一下。
多线程下载原理及步骤:
1、在本地创建一个大小跟服务器文件相同大小的临时文件。
2、计算分配几个线程去下载服务器上的资源,知道每个线程下载文件的位置。

步骤二的具体方法和操作:
文件的长度/3(线程的个数)=每个线程下载文件的大小
假设文件长度为10,则
线程1:0-2
线程2:3-5
线程3:6-文件末尾

每个线程下载的位置的计算方式:
开始位置:
(线程id - 1)* 每一块的大小
结束位置:
(线程id * 每一块大小)-1

3、开启多(3)个线程,每一个线程下载对应位置的文件
4、如果所有的线程都把自己的数据下载完毕了,服务器上的资源就被下载到本地了。


在这里在介绍一个有关多线程下载的java中的相关类RandomAccessFile

RandomAccessFile 随机文件访问类
只有RandomAccessFile才有seek搜寻方法,而这个方法也只适用于文件。通过seek()方法指定位置,定位文件,即可以指定随机写文件的时候从哪个位置开
始写。利用这个类才能实现文件的多线程下载。

基本原理和相关介绍如上,就这些,现在我们看看代码:

package net.loonggg.test;import java.io.InputStream;import java.io.RandomAccessFile;import java.net.HttpURLConnection;import java.net.URL;/*** * 多线程下载 *  * @author loonggg *  */public class MutilDownloader {// 开启的线程的个数public static final int THREAD_COUNT = 3;public static void main(String[] args) throws Exception {String path = "http://down.360safe.com/yunpan/360wangpan_setup.exe";// 连接服务器,获取一个文件,获取文件的长度,在本地创建一个大小跟服务器文件大小一样的临时文件URL url = new URL(path);HttpURLConnection conn = (HttpURLConnection) url.openConnection();// 设置网络请求超时时间conn.setConnectTimeout(5000);// 设置请求方式conn.setRequestMethod("GET");int code = conn.getResponseCode();if (code == 200) {// 服务器返回的数据的长度,实际就是文件的长度int length = conn.getContentLength();System.out.println("----文件总长度----" + length);// 在客户端本地创建出来一个大小跟服务器端文件一样大小的临时文件RandomAccessFile raf = new RandomAccessFile("yunpan.exe", "rwd");// 指定创建的这个文件的长度raf.setLength(length);// 关闭rafraf.close();// 假设是3个线程去下载资源// 平均每一个线程下载的文件的大小int blockSize = length / THREAD_COUNT;for (int threadId = 1; threadId <= THREAD_COUNT; threadId++) {// 计算每个线程下载的开始位置和结束位置int startIndex = (threadId - 1) * blockSize;int endIndex = threadId * blockSize - 1;if (threadId == THREAD_COUNT) {endIndex = length;}System.out.println("----threadId---" + threadId+ "--startIndex--" + startIndex + "--endIndex--"+ endIndex);// 开启每一个线程new DownloadThread(path, threadId, startIndex, endIndex).start();}}}/** * 下载文件的子线程,每一个线程下载对应位置的文件 *  * @author loonggg *  */public static class DownloadThread extends Thread {private int threadId;private int startIndex;private int endIndex;private String path;/** * @param path *            下载文件在服务器上的路径 * @param threadId *            线程id * @param startIndex *            线程下载的开始位置 * @param endIndex *            线程下载的结束位置 */public DownloadThread(String path, int threadId, int startIndex,int endIndex) {this.path = path;this.threadId = threadId;this.startIndex = startIndex;this.endIndex = endIndex;}@Overridepublic void run() {try {URL url = new URL(path);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod("GET");// 重要:请求服务器下载部分的文件 指定文件的位置conn.setRequestProperty("Range", "bytes=" + startIndex + "-"+ endIndex);conn.setConnectTimeout(5000);// 从服务器请求全部资源的状态码200 ok 如果从服务器请求部分资源的状态码206 okint code = conn.getResponseCode();System.out.println("---code---" + code);InputStream is = conn.getInputStream();// 已经设置了请求的位置,返回的是当前位置对应的文件的输入流RandomAccessFile raf = new RandomAccessFile("yunpan.exe", "rwd");// 随机写文件的时候从哪个位置开始写raf.seek(startIndex);// 定位文件int len = 0;byte[] buffer = new byte[1024];while ((len = is.read(buffer)) != -1) {raf.write(buffer, 0, len);}is.close();raf.close();System.out.println("线程" + threadId + ":下载完毕了!");} catch (Exception e) {e.printStackTrace();}}}}

版权声明:本文为博主原创文章,未经博主允许不得转载。

更多相关文章

  1. Android(安卓)Handler机制不一样角度去理解
  2. Android平台调用so库中函数的流程及一些坑
  3. android中的反编译
  4. Android(安卓)热修复其实很简单
  5. 下面就介绍下Android(安卓)NDK的入门学习过程
  6. Android学习系列(3)--App自动更新之自定义进度视图和内部存储
  7. Android开发——实现子线程更新UI
  8. Android应用开发以及设计思想深度剖析(1)
  9. Android(安卓)利用h264流合成mp4

随机推荐

  1. 关于android:background="@drawable/ 出
  2. 3.5 意图Intent的概念
  3. Android UI开发第十二篇——动画效果Anim
  4. android那点事--连上单片机蓝牙模块(csr b
  5. Android之异步处理
  6. Android中的Activity生命周期学习
  7. Android开发者必备的十个工具介绍
  8. Android 4.4(KitKat)窗口管理分系统 - 体
  9. 5个最佳的Android测试框架(带示例)
  10. 那些年,我们一起追的Android