Java实现多线程下载

一.多线程下载

多线程同时操作一个文件
1.首先得知道文件有多大, getContentLengthLong()

2.然后根据线程数分出每一个小块,然后计算出每个小块应该从什么地方下载到什么地方,为了保证数据的完整性,最后一个线程下载剩余所有的字节。

3.通过RandomAcessFile来创建一个可读可写的空白文件,并且设置length为文件的大小,这样就创建了一个XXX大小的空白文件

4.将每个线程应该现在的起点和终点已经文件地址传给下载线程,由下载线程去发起下载,

5.中间需要设置一个请求头,”range”,”bytes=起点-(终点-1)”,如果服务端接受,就会返回206,然后在里面再通过RandomAcessFile来访问原始创建的文件,然后调用seek方法,将偏移量设置为当前线程的下载起点值,然后开始写流,写完OK

setRequestProperty(“range”, “bytes=” + startbyte + “-” + (endbyte - 1))

randomAccessFile.seek(startBytes);

import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * Created by Administrator on 2016/7/26.
 */
public class MultiThreadDownLoadFileDemo {
    private static final String REQUESTFILEPATH = "http://localhost:8080/day14servletdemo/baidu.exe";

    public static void main(String[] args) {
        downLoadFile(REQUESTFILEPATH);
    }

    /**
     * 多线程下载文件
     */
    private static void downLoadFile(String requestPath) {
        //首先的知道文件有多大
        try {
            URL url = new URL(requestPath);
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
            httpURLConnection.setRequestMethod("GET");
            httpURLConnection.setConnectTimeout(5000);
            httpURLConnection.setReadTimeout(5000);
            httpURLConnection.connect();
            if (httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                //返回数据了,可以获取文件大小
                long lenght = httpURLConnection.getContentLengthLong();//获取文件的长度
                //创建一个和目标文件一样大的空白文件
                RandomAccessFile randomAccessFile = new RandomAccessFile("d:/2222.exe", "rw");
                randomAccessFile.setLength(lenght);//设置文件大小
                //根据线程数分块
                int threadCount = 5;
                long blockSize = lenght / 5;//每个线程应该下载多少
                long endbyte;//结束的点
                System.out.println("总长度" + lenght);
                //计算每个线程应该从什么地方下载到什么地方
                for (int i = 0; i < threadCount; i++) {
                    //   i*blockSize  i*blockSize+blockSize
                    if (i == threadCount - 1) {
                        System.out.println("起点" + (i * blockSize) + "结束" + lenght);
                        endbyte = lenght;//当是最后一个线程的时候应该下载剩余的所有的字节
                    } else {
                        System.out.println("起点" + (i * blockSize) + "结束" + (i * blockSize + blockSize));
                        endbyte = i * blockSize + blockSize;//不是最后一个线程

                    }
                    MyDownLoadThread myDownLoadThread = new MyDownLoadThread(i * blockSize, endbyte, requestPath);//创建下载线程
                    myDownLoadThread.start();
                }

            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

多线程下载


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


public class MyDownLoadThread extends Thread {
    private long startbyte, endbyte;//定义每个线程下载的起始和结束位置
    private String filePath;//文件的下载地址
    private long progess;//当前线程的下载进度

    public MyDownLoadThread(long startbyte, long endbyte, String filePath) {
        this.startbyte = startbyte;
        this.endbyte = endbyte;
        this.filePath = filePath;
        this.progess = startbyte;
    }

    @Override
    public void run() {
        try {
            System.out.println(Thread.currentThread().getName() + "开始下载了");
            URL url = new URL(filePath);
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
            httpURLConnection.setConnectTimeout(5000);
            httpURLConnection.setRequestMethod("GET");
            httpURLConnection.setReadTimeout(5000);
            //设置请求头,规定请求数据的范围
            httpURLConnection.setRequestProperty("range", "bytes=" + startbyte + "-" + (endbyte - 1));
            httpURLConnection.connect();
            if (httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_PARTIAL) {//服务端接受我们的分段现在请求 并且返回数据
                //写文件
                RandomAccessFile randomAccessFile = new RandomAccessFile("d:/2222.exe", "rw");//使用随机读写流访问当前下载的文件
                //
                randomAccessFile.seek(startbyte);//设置偏移量,从什么地方开始写流
                InputStream in = httpURLConnection.getInputStream();
                int len = 0;
                byte[] bs = new byte[1024 * 8];
                while ((len = in.read(bs)) != -1) {
                    System.out.println(Thread.currentThread().getName() + "已经下载了" + (progess += len));
                    randomAccessFile.write(bs, 0, len);
                }
                randomAccessFile.close();
                in.close();
                System.out.println(Thread.currentThread().getName() + "下载结束");
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值