多线程下载

package com.zhaoda.zxy.myapplication;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Created by ZXY on 2016/5/23.
 */
public class MutilDownload2 {
    //[1]定义h下载路径
    private static String path = "http://172.17.242.1:8080/as.exe";
    private static final int threadCount = 3;//假设开三个线程
    private static int runningThread;//代表当前正在运行的线程

    public static void main(String[] args) {
//[一☆☆☆☆☆]获取服务器文件大小,要计算每个线程的下载开始的位置和结束位置
        try {
            //1.创建url对象参数就是网址
            URL url = new URL(path);
            //2.获取HttpURLConnecton链接对象
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            //3.设置参数发送get请求
            conn.setRequestMethod("GET");
            //4.设置链接网路的超时时间
            conn.setConnectTimeout(5000);
            //5.获取服务器返回状态码
            int code = conn.getResponseCode();
            if (code == 200) {//200代表获取服务器资源全部成功,206请求部分资源
                //6.获取服务器文件的大小
                int length = conn.getContentLength();
                //6.1把线程的数量赋给正在运行的线程
                runningThread = threadCount;
                //[二☆☆☆☆☆]创建大小和服务器一模一样的文件目的提前把空间申请出来
                RandomAccessFile raf = new RandomAccessFile("temp.exe", "rw");
                raf.setLength(length);
                //7.算出每个线程下载的大小
                int blockSize = length / threadCount;
                //[三☆☆☆☆☆]计算每个线程开始位置和结束位置
                for (int i = 0; i < threadCount; i++) {
                    int startIndex = i * blockSize;//每个线程下载开始位置
                    int endIndex = (i + 1) * blockSize - 1;
                    if (i == threadCount - 1) {
                        //说明是最好一个线程
                        endIndex = length - 1;
                    }
                    System.out.println("线程id:" + i + "理论下载位置" + ":" + startIndex + "----" + endIndex);

                    //[四☆☆☆☆☆]开启线程去服务器下载文件
                    DownLoadThread downLoadThread = new DownLoadThread(startIndex, endIndex, i);
                    downLoadThread.start();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //定义线程去服务器下载文件
    private static class DownLoadThread extends Thread {
        //通过构造方法把每个线程下载的开始位置和结束位置
        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 {
                //1.创建url对象参数就是网址
                URL url = new URL(path);
                //2.获取HttpURLConnecton链接对象
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                //3.设置参数发送get请求
                conn.setRequestMethod("GET");
                //4.设置链接网路的超时时间
                conn.setConnectTimeout(5000);
                //4.0如果下载中间断过,继续上次的位置继续下载,从文件中读取上次下载的位置
                File file = new File(getFilename(path) + threadId + ".txt");
                if (file.exists() && file.length() > 0) {
                    FileInputStream fis = new FileInputStream(file);
                    BufferedReader bufr = new BufferedReader(new InputStreamReader(fis));
                    String lastPositionn = bufr.readLine();//读取出来内容就是上次下载位置
                    int lastPosition = Integer.parseInt(lastPositionn);
                    //4.0.1要改变startIndex位置
                    startIndex = lastPosition;
                    System.out.println("线程id:" + threadId + "真实下载位置" + ":" + startIndex + "----" + endIndex);
                    fis.close();
                }
                //4.1设置一个请求头Range(作用告诉服务器每个线程下载的开始位置和结束位置)
                conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
                //5.获取服务器返回状态码
                int code = conn.getResponseCode();
                if (code == 206) {//200代表获取服务器资源全部成功,206请求部分资源
                    //6.创建随机读写文件对象
                    RandomAccessFile raf = new RandomAccessFile(getFilename(path), "rw");
                    //6.1每个线程都从自己位置开始写
                    raf.seek(startIndex);
                    InputStream in = conn.getInputStream();//获取服务器文件
                    //7.把数据写到文件中.
                    int len = -1;
                    byte[] buffer = new byte[1024 * 1024];
                    int total = 0;//当前线程下载的大小
                    while ((len = in.read(buffer)) != -1) {
                        raf.write(buffer, 0, len);
                        total += len;
                        //8.实现断点续传就是把当前线程下载的位置存起来,下次再下载就是按照上次下载位置继续下载就行了
                        int currrentThreadPosition = startIndex + total;//占时存在txt文本中
                        //q.用来存当前线程下载的位置
                        RandomAccessFile raff = new RandomAccessFile(getFilename(path) + threadId + ".txt", "rwd");
                        raff.write(String.valueOf(currrentThreadPosition).getBytes());
                        raff.close();
                    }
                    raf.close();//关闭流,释放资源
                    System.out.println("线程id:" + threadId + "下载完毕!");
                    //10.把.txt文件删除
                    synchronized (DownLoadThread.class) {
                        runningThread--;
                        if (runningThread == 0) {
                            //说明所有线程都执行完毕了,就把.txt文件删除了
                            for (int i = 0; i < threadCount; i++) {
                                File delteFile = new File(getFilename(path) + i + ".txt");
                                delteFile.delete();

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

    //获取文件的名字  http://172.17.242.1:8080/as.exe
    public static String getFilename(String path) {
        int start = path.lastIndexOf("/") + 1;
        return path.substring(start);
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值