多线程下载

最近学习了线程这一块,发现很有意思,就把自己写的代码保存下来为了更好的学习与交流
多线程下载注意的关键:
1:先明白多线程下载的原理,明白原理后,实现代码已经理解代码就不难。
2:如何确定下载文件的总大小
3:根据文件总大小和线程数量,来确定每个线程下载的起始位置和结束位置,以及最后一个线程他负责大小的特殊性。
4:执行线程下载的时候,要设置本次http请求所请求的数据的区间,也就是开始位置和结束为止。响应码返回值是206而不是200.
connection.setRequestProperty(“Range”, “bytes=” + startIndex + “-” + endIndex);
/************************************************************************************/

package com.cnu.multithreaddownload;

import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import javax.net.ssl.HttpsURLConnection;

public class MultiThreadDownload {
static int ThreadCount = 3;
// 确定下载地址,这是本地Tomcat上一个地址
static String path = “http://10.1.156.35:8080/adsafese.v1.1.1.9900.exe“;

public static void main(String[] args) {

    // 发送get请求,请求这个地址的资源.第一次发送get请求,是为了得到文件的长度,而不是下载

    try {
        URL url = new URL(path);
        HttpURLConnection connection = (HttpURLConnection) url
                .openConnection();
        connection.setRequestMethod("GET");
        connection.setConnectTimeout(5000);
        connection.setReadTimeout(5000);
        if (connection.getResponseCode() == 200) {
            // 拿到所请求资源文件的长度
            int length = connection.getContentLength();
            File file = new File("adsafese.v1.1.1.9900.exe");  //默认会在项目根路径上
            // 生成临时文件
            RandomAccessFile raf = new RandomAccessFile(file, "rwd");
            // 设置临时文件的大小
            raf.setLength(length);
            raf.close();
            // 计算出每个线程应该下载多少个字节
            int size = length / ThreadCount;
            for (int i = 0; i < ThreadCount; i++) {
                // 计算线程下载的开始位置和结束位置
                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(MultiThreadDownload.path);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setConnectTimeout(5000);
        connection.setReadTimeout(5000);
        //设置本次http请求所请求的数据的区间
        connection.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
        //请求部分数据,响应码是206
        if (connection.getResponseCode() == 206) {
            InputStream is = connection.getInputStream();
            byte[] b = new byte[1024];
            int len = 0;
            int total = 0;
            //拿到临时文件的输入流
            File file = new File("adsafese.v1.1.1.9900.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 + "下载完毕--------------------------------------------------------------------"  );
        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值