本文主要包含多线程下载的一些简单demo,包括三部分

  1. java实现
  2. android实现
  3. XUtils开源库实现

注意下载添加网络权限与SD卡读写权限

java实现多线程下载

public class MutileThreadDownload {/*** 线程的数量*/private static int threadCount = 3;/*** 每个下载区块的大小*/private static long blocksize;/*** 正在运行的线程的数量*/private static int runningThreadCount;/*** @param args* @throws Exception*/public static void main(String[] args) throws Exception {// 服务器文件的路径String path = "http://192.168.1.100:8080/ff.exe";URL url = new URL(path);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod("GET");conn.setConnectTimeout(5000);int code = conn.getResponseCode();if (code == 200) {long size = conn.getContentLength();// 得到服务端返回的文件的大小System.out.println("服务器文件的大小:" + size);blocksize = size / threadCount;// 1.首先在本地创建一个大小跟服务器一模一样的空白文件。File file = new File("temp.exe");RandomAccessFile raf = new RandomAccessFile(file, "rw");raf.setLength(size);// 2.开启若干个子线程分别去下载对应的资源。runningThreadCount = threadCount;for (int i = 1; i <= threadCount; i++) {long startIndex = (i - 1) * blocksize;long endIndex = i * blocksize - 1;if (i == threadCount) {// 最后一个线程endIndex = size - 1;}System.out.println("开启线程:" + i + "下载的位置:" + startIndex + "~"+ endIndex);new DownloadThread(path, i, startIndex, endIndex).start();}}conn.disconnect();}private static class DownloadThread extends Thread {private int threadId;private long startIndex;private long endIndex;private String path;public DownloadThread(String path, int threadId, long startIndex,long endIndex) {this.path = path;this.threadId = threadId;this.startIndex = startIndex;this.endIndex = endIndex;}@Overridepublic void run() {try {// 当前线程下载的总大小int total = 0;File positionFile = new File(threadId + ".txt");URL url = new URL(path);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod("GET");// 接着从上一次的位置继续下载数据if (positionFile.exists() && positionFile.length() > 0) {// 判断是否有记录FileInputStream fis = new FileInputStream(positionFile);BufferedReader br = new BufferedReader(new InputStreamReader(fis));// 获取当前线程上次下载的总大小是多少String lasttotalstr = br.readLine();int lastTotal = Integer.valueOf(lasttotalstr);System.out.println("上次线程" + threadId + "下载的总大小:"+ lastTotal);startIndex += lastTotal;total += lastTotal;// 加上上次下载的总大小。fis.close();}conn.setRequestProperty("Range", "bytes=" + startIndex + "-"+ endIndex);conn.setConnectTimeout(5000);int code = conn.getResponseCode();System.out.println("code=" + code);InputStream is = conn.getInputStream();File file = new File("temp.exe");RandomAccessFile raf = new RandomAccessFile(file, "rw");// 指定文件开始写的位置。raf.seek(startIndex);System.out.println("第" + threadId + "个线程:写文件的开始位置:"+ String.valueOf(startIndex));int len = 0;byte[] buffer = new byte[512];while ((len = is.read(buffer)) != -1) {RandomAccessFile rf = new RandomAccessFile(positionFile,"rwd");raf.write(buffer, 0, len);total += len;rf.write(String.valueOf(total).getBytes());rf.close();}is.close();raf.close();} catch (Exception e) {e.printStackTrace();} finally {// 只有所有的线程都下载完毕后 才可以删除记录文件。synchronized (MutileThreadDownload.class) {System.out.println("线程" + threadId + "下载完毕了");runningThreadCount--;if (runningThreadCount < 1) {System.out.println("所有的线程都工作完毕了。删除临时记录的文件");for (int i = 1; i <= threadCount; i++) {File f = new File(i + ".txt");System.out.println(f.delete());}}}}}}
}

安卓实现

public class MainActivity extends Activity {protected static final int DOWNLOAD_ERROR = 1;private static final int THREAD_ERROR = 2;public static final int DWONLOAD_FINISH = 3;private EditText et_path;private EditText et_count;/*** 存放进度条的布局*/private LinearLayout ll_container;/*** 进度条的集合*/private List<ProgressBar> pbs;/*** android下的消息处理器,在主线程创建,才可以更新ui*/private Handler handler = new Handler(){public void handleMessage(Message msg) {switch (msg.what) {case DOWNLOAD_ERROR:Toast.makeText(getApplicationContext(), "下载失败", 0).show();break;case THREAD_ERROR:Toast.makeText(getApplicationContext(), "下载失败,请重试", 0).show();break;case DWONLOAD_FINISH:Toast.makeText(getApplicationContext(), "下载完成", 0).show();break;}};};/*** 线程的数量*/private int threadCount = 3;/*** 每个下载区块的大小*/private long blocksize;/*** 正在运行的线程的数量*/private  int runningThreadCount;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);et_path = (EditText) findViewById(R.id.et_path);et_count = (EditText) findViewById(R.id.et_count);ll_container = (LinearLayout) findViewById(R.id.ll_container);}/*** 下载按钮的点击事件* @param view*/public void downLoad(View view){//下载文件的路径final String path = et_path.getText().toString().trim();if(TextUtils.isEmpty(path)){Toast.makeText(this, "对不起下载路径不能为空", 0).show();return;}String count = et_count.getText().toString().trim();if(TextUtils.isEmpty(path)){Toast.makeText(this, "对不起,线程数量不能为空", 0).show();return;}threadCount = Integer.parseInt(count);//清空掉旧的进度条ll_container.removeAllViews();//在界面里面添加count个进度条pbs = new ArrayList<ProgressBar>();for(int j=0;j<threadCount;j++){ProgressBar pb = (ProgressBar) View.inflate(this, R.layout.pb, null);ll_container.addView(pb);pbs.add(pb);}Toast.makeText(this, "开始下载", 0).show();new Thread(){public void run() {try {URL url = new URL(path);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod("GET");conn.setConnectTimeout(5000);int code = conn.getResponseCode();if (code == 200) {long size = conn.getContentLength();// 得到服务端返回的文件的大小System.out.println("服务器文件的大小:" + size);blocksize = size / threadCount;// 1.首先在本地创建一个大小跟服务器一模一样的空白文件。File file = new File(Environment.getExternalStorageDirectory(),getFileName(path));RandomAccessFile raf = new RandomAccessFile(file, "rw");raf.setLength(size);// 2.开启若干个子线程分别去下载对应的资源。runningThreadCount = threadCount;for (int i = 1; i <= threadCount; i++) {long startIndex = (i - 1) * blocksize;long endIndex = i * blocksize - 1;if (i == threadCount) {// 最后一个线程endIndex = size - 1;}System.out.println("开启线程:" + i + "下载的位置:" + startIndex + "~"+ endIndex);int threadSize = (int) (endIndex - startIndex);pbs.get(i-1).setMax(threadSize);new DownloadThread(path, i, startIndex, endIndex).start();}}conn.disconnect();} catch (Exception e) {e.printStackTrace();Message msg = Message.obtain();msg.what = DOWNLOAD_ERROR;handler.sendMessage(msg);}};}.start();}private class DownloadThread extends Thread {private int threadId;private long startIndex;private long endIndex;private String path;public DownloadThread(String path, int threadId, long startIndex,long endIndex) {this.path = path;this.threadId = threadId;this.startIndex = startIndex;this.endIndex = endIndex;}@Overridepublic void run() {try {// 当前线程下载的总大小int total = 0;File positionFile = new File(Environment.getExternalStorageDirectory(),getFileName(path)+threadId + ".txt");URL url = new URL(path);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod("GET");// 接着从上一次的位置继续下载数据if (positionFile.exists() && positionFile.length() > 0) {// 判断是否有记录FileInputStream fis = new FileInputStream(positionFile);BufferedReader br = new BufferedReader(new InputStreamReader(fis));// 获取当前线程上次下载的总大小是多少String lasttotalstr = br.readLine();int lastTotal = Integer.valueOf(lasttotalstr);System.out.println("上次线程" + threadId + "下载的总大小:"+ lastTotal);startIndex += lastTotal;total += lastTotal;// 加上上次下载的总大小。fis.close();//存数据库。//_id path threadid total}conn.setRequestProperty("Range", "bytes=" + startIndex + "-"+ endIndex);conn.setConnectTimeout(5000);int code = conn.getResponseCode();System.out.println("code=" + code);InputStream is = conn.getInputStream();File file = new File(Environment.getExternalStorageDirectory(),getFileName(path));RandomAccessFile raf = new RandomAccessFile(file, "rw");// 指定文件开始写的位置。raf.seek(startIndex);System.out.println("第" + threadId + "个线程:写文件的开始位置:"+ String.valueOf(startIndex));int len = 0;byte[] buffer = new byte[1024];while ((len = is.read(buffer)) != -1) {RandomAccessFile rf = new RandomAccessFile(positionFile,"rwd");raf.write(buffer, 0, len);total += len;rf.write(String.valueOf(total).getBytes());rf.close();pbs.get(threadId-1).setProgress(total);}is.close();raf.close();} catch (Exception e) {e.printStackTrace();Message msg = Message.obtain();msg.what = THREAD_ERROR;handler.sendMessage(msg);} finally {// 只有所有的线程都下载完毕后 才可以删除记录文件。synchronized (MainActivity.class) {System.out.println("线程" + threadId + "下载完毕了");runningThreadCount--;if (runningThreadCount < 1) {System.out.println("所有的线程都工作完毕了。删除临时记录的文件");for (int i = 1; i <= threadCount; i++) {File f = new File(Environment.getExternalStorageDirectory(),getFileName(path)+ i + ".txt");System.out.println(f.delete());}Message msg = Message.obtain();msg.what = DWONLOAD_FINISH;handler.sendMessage(msg);}}}}}//http://192.168.1.100:8080/aa.exeprivate String getFileName(String path){int start = path.lastIndexOf("/")+1;return path.substring(start);}}

利用XUtils开源框架实现,需要XUtils的jar包

public class MainActivity extends Activity {private EditText et_path;private TextView tv_info;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);et_path = (EditText) findViewById(R.id.et_path);tv_info = (TextView) findViewById(R.id.tv_info);}public void download(View view){String path = et_path.getText().toString().trim();if(TextUtils.isEmpty(path)){Toast.makeText(this, "请输入下载的路径", 0).show();return;}else{HttpUtils http = new HttpUtils();HttpHandler handler = http.download(path,"/sdcard/xxx.zip",true, // 如果目标文件存在,接着未完成的部分继续下载。服务器不支持RANGE时将从新下载。true, // 如果从请求返回信息中获取到文件名,下载完成后自动重命名。new RequestCallBack<File>() {@Overridepublic void onStart() {tv_info.setText("conn...");}@Overridepublic void onLoading(long total, long current, boolean isUploading) {tv_info.setText(current + "/" + total);}@Overridepublic void onSuccess(ResponseInfo<File> responseInfo) {tv_info.setText("downloaded:" + responseInfo.result.getPath());}@Overridepublic void onFailure(HttpException error, String msg) {tv_info.setText(msg);}});}}
}

完成

Android之多线程断点下载相关推荐

  1. android学习笔记---31_多线程断点下载器,下载原理实现

    1.1.31_多线程断点下载器 ----------------------- 1.软件界面:   文件下载路径              text框   button 下载   点击后,下面显示下载 ...

  2. android 多线程断点下载,listview 模式 开始 暂停等功能

    android 多线程断点下载,listview 模式 代码依次如下: 布局: <?xml version="1.0" encoding="utf-8"? ...

  3. 即拿即用-Android多线程断点下载

    线程下载只需要确定好下载一个文件需要多少个线程,一般来说最好为3条线程,因为线程过多会占用系统资源,而且线程间的相互竞争也会导致下载变慢. 其次下载的时候将文件分割为三份(假设用3条线程下载)下载,在 ...

  4. 安卓客户端的多线程断点下载(SharedPreferences版)

    题记:从百度百科上面我们知道,SharedPreferences是不支持多线程的,但是这次使用SharedPreferences实现了多线程断点下载.点解? 服务器端: 使用的是tomcat服务器,在 ...

  5. iOS开发网络篇—多线程断点下载

    iOS开发网络篇-多线程断点下载 说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了同时开启多条线程下载一个较大的文件.因为实现过程较为复杂,所以下面贴出完整的代码. 实现思路:下载开始, ...

  6. Java多线程断点下载

    多线程下载已经提高了下载的效率,但是当一些特殊情况发生的时候,我们需要对程序进行处理,这样效率会更高.比如,断电断网等造成下载中断,那么我们下一次又要重新开始下载,这样效率底下,所以我们可以考虑使用断 ...

  7. Android 多线程断点下载demo实现

    先来一张效果图: 主要实现思路: 每一个下载都是通过RandomAccessFile对下载资源的总长进行切割之后,根据我们设置的线程多少进行计算之后开启多线程下载的.而每一个任务都是一个AsyncTa ...

  8. Android多线程断点下载

    到华为后,信息管理特别严格,文件不能外发.所以好久都没写博客了,今天周日,老婆非要我学习.就闲来无事,写一篇博客,呵呵-- 前段时间,项目中提到了断点下载apk并静默安装的需求.本打算用应用市场成熟的 ...

  9. Android(java)学习笔记158:多线程断点下载的原理(JavaSE实现)

    1. 为什么需要多线程下载?     服务器的资源有限,同时的平均地分配给每个客户端.开启的线程越多抢占的服务的资源就越多,下载的速度就越块. 2. 下载速度的限制条件? (1)你的电脑手机宽带的带宽 ...

最新文章

  1. create_pose算子说明
  2. 【收藏】IDEA jetbrains.com官网进不去解决办法
  3. QML基础类型之geopath
  4. 简化从Win32到Windows 10的迁移之路
  5. vue删除数组中的一条数据_删除排序数组中的重复项 II
  6. 焦头烂额一个上午还是搞不定,跪地相求大家,朋友帮忙啊。。。
  7. 如何给对方邮箱发照片_朋友圈如何发心形拼图九宫格照片?
  8. 马云还曾有过这么一段求职经历
  9. vivo S10 PRO怎么解锁vivoS10解锁平台刷机教程屏幕锁激活手机锁不记得了可以用这个方法教程重装系统固件软件程序使用方法流程
  10. matlab2009a安装包,matlab2009a安装
  11. IA-32 Intel®架构软件开发人员手册卷3:系统编程指南(中文版-部分)
  12. for..in loops iterate over the entire prototype chain
  13. python函数名前带个杠
  14. CSS字体透明度怎么设置?
  15. java生成不可修改的pdf_好記性不如爛筆頭4-JAVA生成PDF文件
  16. 集散控制系统是集计算机技术,集散控制系统概述
  17. 作为一名后端开发,核心竞争力是什么?
  18. Windows影射模式
  19. 百度搜狗神马搜索劫持 来源网站跳转 快照霸屏 竞价劫持 霸屏代码
  20. 字符和字节的区别与分析

热门文章

  1. 人工智能在线特征系统中的数据存取技术
  2. 云原生之容器安全实践
  3. 最全多线程经典面试题和答案
  4. java架构师进阶之独孤九剑(一)-算法思想与经典算法
  5. 论文浅尝 | 基于知识图谱的智能调研方法(DI佳作)
  6. 论文浅尝 | GNN with Generated Parameters for Relation Extraction
  7. 论文浅尝 | 基于知识图谱中图卷积神经网络的推荐系统
  8. 论文浅尝 | 面向自动分类归纳的端到端强化学习
  9. Pytorch与tensorflow模型转换
  10. 我们的实践: 400万全行业动态事理图谱Demo