java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 程序设计语言和 Java 平台(即 JavaEE(j2ee), JavaME(j2me), JavaSE(j2se))的总称。
这篇文章主要介绍了 java 多线程实现文件下载功能的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
多线程下载文件的思路:
1. 首先获取到文件的总大小
获取文件大小的方式是通过网络读取,getContentLength() 即可获取到文件的大小,使用 RandomAccessFile() 支持随机访问
2. 根据所准备的线程数据,计算每一个线程需要下载的文件的大小
上图显示下载 400M 的电影分 4 个线程下载,每一个线程分别下载各自数据段中的数据,第一个线程下载 0-100M,第二个下载 100M-200M 之间的数据,依次类推。因此下载过程中需要记住的是的开始位置段和结束位置段,其实只需要开始位置就可以了,结束为止可以根据开始位置加上下载的大小来推断获取。
3. 获取到大小数据以后,开始用线程循环读取每一个区间的数据
这个里面需要注意的是,要更新数据的写入位置 seek(startIndex),逐段填满,不然会出现覆盖以前的数据。
- package com.ldw.multilthreaddownload;
- import java.io.File;
- import java.io.InputStream;
- import java.io.RandomAccessFile;
- import java.net.HttpURLConnection;
- import java.net.URL;
- public class Multidownload {
- static int ThreadCount = 3; //线程的个数
- static String path = "http://192.168.0.102:8080/QQ.exe"; //确定下载地址
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- //发送get请求,请求这个地址的资源
- try {
- URL url = new URL(path);
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- conn.setRequestMethod("GET");
- conn.setConnectTimeout(5000);
- conn.setReadTimeout(5000);
- if (conn.getResponseCode() == 200) {
- //获取到请求资源文件的长度
- int length = conn.getContentLength();
- File file = new File("QQ.exe");
- //创建随机存储文件
- RandomAccessFile raf = new RandomAccessFile(file, "rwd");
- //设置临时文件的大小
- raf.setLength(length);
- //关闭raf
- raf.close();
- //计算出每一个线程下载多少字节
- int size = length / Multidownload.ThreadCount;
- for (int i = 0; i < Multidownload.ThreadCount; i++) {
- //startIndex,endIndex分别代表线程的开始和结束位置
- int startIndex = i * size;
- int endIndex = (i + 1) * size - 1;
- if (i == ThreadCount - 1) {
- //如果是最后一个线程,那么结束位置写死
- endIndex = length - 1;
- }
- System.out.println("线程" + i + "的下载区间是" + startIndex + "到" + endIndex);
- new DownLoadThread(startIndex, endIndex, i).start(); //创建线程下载数据
- }
- }
- } catch(Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- class DownLoadThread extends Thread {
- int startIndex;
- int endIndex;
- int threadId;
- public DownLoadThread(int startIndex, int endIndex, int threadId) {
- super();
- this.startIndex = startIndex;
- this.endIndex = endIndex;
- this.threadId = threadId;
- }
- @Override public void run() {
- //使用http请求下载安装包文件
- URL url;
- try {
- url = new URL(Multidownload.path);
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- conn.setRequestMethod("GET");
- conn.setConnectTimeout(5000);
- conn.setReadTimeout(5000);
- //设置请求数据的区间
- conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
- //请求部分数据的响应码是206
- if (conn.getResponseCode() == 206) {
- //获取一部分数据来读取
- InputStream is = conn.getInputStream();
- byte[] b = new byte[1024];
- int len = 0;
- int total = 0;
- //拿到临时文件的引用
- File file = new File("QQ.exe");
- RandomAccessFile raf = new RandomAccessFile(file, "rwd");
- //更新文件的写入位置,startIndex
- raf.seek(startIndex);
- while ((len = is.read(b)) != -1) {
- //每次读取流里面的数据,同步吧数据写入临时文件
- raf.write(b, 0, len);
- total += len;
- System.out.println("线程" + threadId + "下载了" + total);
- }
- System.out.println("线程" + threadId + "下载过程结束===========================");
- raf.close();
- }
- } catch(Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- };
- }
来源: http://www.phperz.com/article/17/1219/358786.html