多线程下载

23 篇文章 0 订阅
20 篇文章 0 订阅

好久没有更新博客了 ,今天写了一篇多线程下载并可以实现暂停之后继续下载,文章还有很多改进的地方, 望大神们不吝赐教

package mutildownload1;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * HttpURLConnection 使用步骤
 * A:URl url=new URL() 将字符串变为java程序可以识别的url地址
 * B:HttpURLConnection con=(HttpURLConnection)url.openConection() 打开一个HttpURLConnection 的链接
 * C:con.setRequestMethod();设置请求方式 GET或POST
 * D:con.setConnectTimeout();设置允许多长时间没反应
 * E:con.getResponseCode();获取求状态码 200 获取整个文件成功 206 获取部分文件成功
 *
 */
public class MutilDownload2 {
    /**
     * 多线程下载(可以实现断点续传)
     * 实现思路:
     * (多线程下载)
     * A:获取文件总大小 con.getContentLength()
     * B:将获取到的大小按照你准备的线程数进行分配 并计算出每个线程下载的起始位置
     * C:开启多个线程下载
     * D:因为是多线程下载 所以得设置好每个线程真正下载的起始位置(这是一句死的 照写就行)
     *  con.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
     *
     * (断点续传)
     * E:在读取文件的时候可能出现中断 这个时候我们需要把当前线程下载到哪儿了的位置记住,并写进以当前线程为名字的.txt文件中
     * F:在进入每个线程下载之前 先去文件读一读 有没有以线程名+.txt的文件存在,
     *    如果存在并且文件大于0,就把文件中存储的线程位置读出来,并赋值给当前线程的开始位置,然后继续下载
     *
     */
    private static final String path = "http://172.24.48.43:8080/2.exe";
    private static final int ThreadIdcount = 3;

    public static void main(String args[]) {

        try {
            URL url = new URL(path);
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            con.setRequestMethod("GET");
            con.setConnectTimeout(5000);
            int code = con.getResponseCode();
            if (code == 200) {
                int length = con.getContentLength();//取得要下载文件的总大小
                int blockSize = length / ThreadIdcount;//计算出每个线程应该下载多少
                for (int i = 0; i < ThreadIdcount; i++) {//计算出每个线程下载的起始位置和结束位置
                    int startIndex = i * blockSize;
                    int endIndex = (i + 1) * blockSize;
                    if (i == ThreadIdcount - 1) {//最后一个线程就多下载点
                        endIndex = length - 1;
                    }
                    DownloadThread thread = new DownloadThread(startIndex, endIndex, i);
                    new Thread(thread).start();//开启多个线程下载
                }

            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static class DownloadThread implements Runnable {
        private int startIndex;
        private int endIndex;
        private int threadId;

        public DownloadThread(int startIndex, int endIndex, int threadId) {
            this.startIndex = startIndex;
            this.endIndex = endIndex;
            this.threadId = threadId;
        }

        @Override
        public void run() {
            try {
                URL url = new URL(path);
                HttpURLConnection con = (HttpURLConnection) url.openConnection();
                con.setRequestMethod("GET");
                con.setConnectTimeout(5000);
                File file=new File(threadId+".txt");
                if(file.exists()&&file.length()>0){
                    BufferedReader reader = new BufferedReader(new FileReader(file));
                    String line = reader.readLine();
                    int lastPostion = Integer.parseInt(line);
                    startIndex=lastPostion+1;
                }
                //设置每个线程真正下载的开始和结束位置
                con.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);

                int code = con.getResponseCode();
                int total = 0;
                if (code == 206) {//206代表获取部分资源成功. 这里是线程下载,所以状态码用206

                    //这里使用RandomAccessFile类的目的在于 可以指定文件写入的位置
                    RandomAccessFile rw = new RandomAccessFile("sql.exe", "rw");
                    //指定文件写入的位置
                    rw.seek(startIndex);
                    InputStream in = con.getInputStream();
                    int len = -1;
                    byte[] bs = new byte[1024 * 1024];
                    while (-1 != (len = in.read(bs))) {
                        total += len;
                        int currentPostionToatal = startIndex + total;//当前线程的大小
                        RandomAccessFile rff= new RandomAccessFile(threadId + ".txt","rwd");
                        rff.write(String.valueOf(currentPostionToatal).getBytes());
                        rw.write(bs, 0, len);
                        rff.close();
                    }
                    rw.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }


        }
    }


}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值