Java实现多线程下载、断点续传

开三个线程下载,代码:

package demo;

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

public class MutilDownLoad {

    // 放在Tomcat下的一个文件
    static String path = "http://192.168.87.1:8080/lol.exe";

    // 多线程的个数(开3个线程)
    private static final int THREADACOUNT = 3;

    public static void main(String[] args) {
        try {
            URL url = new URL(path);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5000);

            int code = conn.getResponseCode();
            if (code == 200) {
                // 获取文件大小
                int length = conn.getContentLength();

                // 创建一个和服务器获取的文件大小一致的文件
                RandomAccessFile randomAccessFile = new RandomAccessFile("lol.exe", "rw");
                randomAccessFile.setLength(length);

                // 算出每个线程下载大小
                int blockSize = length / THREADACOUNT;

                // 计算每个线程的起始位置和结束位置
                for (int i = 0; i < THREADACOUNT; i++) {
                    int startIndex = i * blockSize;
                    int endIndex = (i + 1) * blockSize - 1;
                    // 处理最后一个线程结束位置
                    if (i == THREADACOUNT - 1) {
                        endIndex = length - 1;
                    }

                    // 开启多线程下载
                    new DowdLoadThread(startIndex, endIndex, i).start();

                }

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

    // 定义多线程下载文件
    private static class DowdLoadThread extends Thread {
        private int startIndex;
        private int endIndex;
        private int threadID;

        public DowdLoadThread(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 conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                conn.setConnectTimeout(5000);

                // 设置
                conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);

                int code = conn.getResponseCode();
                // 请求部分资源成功(206)
                if (code == 206) {
                    // 随机读写文件对象
                    RandomAccessFile randomAccessFile = new RandomAccessFile("lol.exe", "rw");

                    randomAccessFile.seek(startIndex);

                    InputStream in = conn.getInputStream();

                    // 当前线程下载的大小

                    int len = -1;
                    byte[] buffer = new byte[1024];
                    while ((len = in.read(buffer)) != -1) {
                        randomAccessFile.write(buffer, 0, len);

                    }
                    randomAccessFile.close();

                    System.out.println("线程id:" + threadID + "已下载完毕");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }
}

执行:

接下来实现断点续传:

package demo;

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;

public class MutilDownLoad {

    // 定义下载的路径
    private static String path = "http://192.168.87.1:8080/lol.exe";

    // 假设开三个线程
    private static final int threadCount = 3;

    // 代表当前正在运行的线程
    private static int runningThread;

    public static void main(String[] args) {

        try {

            URL url = new URL(path);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5000);
            int code = conn.getResponseCode();
            if (code == 200) {

                int length = conn.getContentLength();

                runningThread = threadCount;

                System.out.println("length:" + length);

                RandomAccessFile rafAccessFile = new RandomAccessFile(getFilename(path), "rw");
                rafAccessFile.setLength(length);

                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 {
                URL url = new URL(path);

                HttpURLConnection conn = (HttpURLConnection) url.openConnection();

                conn.setRequestMethod("GET");

                conn.setConnectTimeout(5000);

                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);

                    startIndex = lastPosition + 1;

                    System.out.println("线程id::" + threadId + "真实下载的位置" + ":" + startIndex + "-----" + endIndex);

                    fis.close();
                }

                conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);

                int code = conn.getResponseCode();

                if (code == 206) {

                    RandomAccessFile raf = new RandomAccessFile(getFilename(path), "rw");

                    raf.seek(startIndex);

                    InputStream in = conn.getInputStream();

                    int len = -1;
                    byte[] buffer = new byte[1024 * 1024];// 1Mb

                    int total = 0;

                    while ((len = in.read(buffer)) != -1) {
                        raf.write(buffer, 0, len);

                        total += len;
                        // 实现断点续传 就是把当前线程下载的位置 给存起来 下次再下载的时候 就是按照上次下载的位置继续下载
                        // 存到一个普通的.txt文本中
                        int currentThreadPosition = startIndex + total;

                        RandomAccessFile raff = new RandomAccessFile(getFilename(path) + threadId + ".txt", "rwd");
                        raff.write(String.valueOf(currentThreadPosition).getBytes());
                        raff.close();

                    }
                    raf.close();

                    System.out.println("线程id:" + threadId + "---下载完毕了");

                    // 把.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();
            }

        }
    }

    // 获取文件的名字
    public static String getFilename(String path) {

        int start = path.lastIndexOf("/") + 1;
        return path.substring(start);
    }

}

原文地址:https://www.cnblogs.com/xuyiqing/p/8883926.html

时间: 2024-10-18 22:53:24

Java实现多线程下载、断点续传的相关文章

java实现多线程下载

本篇博客可认为是对 使用java实现http多线程下载 一文的再次解读. 首先,从宏观来说 java实现多线程下载这个功能的实现由以下几部分组成: 1 建立多个线程去分别下载文件的一部分. 2 将多个线程下载的文件(还在内存中),写入硬盘中的一个文件. 3 断点续传 GET /Path/FileName HTTP/1.0 Host: www.server.com:80 Accept: */* User-Agent: GeneralDownloadApplication Connection: c

Java--使用多线程下载,断点续传技术原理(RandomAccessFile)

一.基础知识 1.什么是线程?什么是进程?它们之间的关系? 可以参考之前的一篇文章:java核心知识点学习----并发和并行的区别,进程和线程的区别,如何创建线程和线程的四种状态,什么是线程计时器 简单说一个进程可以由多个线程组成,一个操作系统可以多个进程,它们都是可以同时进行工作的. 2.什么是下载?如何多线程进行下载?如何断点续传? 广义上说,凡是在屏幕上看到的不属于本地计算机上的内容,皆是通过"下载"得来.狭义上人们只认为那些自定义了下载文件的本地磁盘存储位置的操作才是"

多线程下载 断点续传

package wml.dl;import java.io.BufferedInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.net.HttpURLConnection;import java.util.Properties; import wml.dl.io.BufferedRandomOutputStream; *

Android多线程下载断点续传

先上图看卡结果: GITHUB:Android多线程下载断点续传 如图所示点击下载就开始下载,点击停止就会停止再次点击下载就会接着下载了. 设计思路是这样的: 首先通过广播将下载信息传递给DownService,DownService根据文件URL获取文件大小,再通过DownTask将下载任务分配,并且通过广播当点击停止下载时将下载进度保存在数据库中,当点击开始下载时再从数据库中获取到保存的进度,继续下载. 代码结构: 核心类是 DownLoadService,java 和DownTask.ja

Java之多线程下载

多线程下载的原理在于,每个线程下载文件的一部分,每个线程将自己下载的一部分写入文件中它应该的位置,所有线程下载完成时,文件下载完成.其关键点在于:RandomAccessFile.seek(beginIndex)和URLConnection.setRequestProperty("Range", "bytes=" + beginIndex + "-" + endIndex). 转载请注明原创地址,请尊重原创,谢谢. 代码如下,以下代码copy后可

Java实现多线程下载 URL以及URLConnection

主线程: public class MultiThreadDown { public static void main(String[] args) throws Exception{ //初始化Downutil对象 final DownUtil downutil = new DownUtil("http://www.crazyit.org/" +"attachment.PHP?aid=MTY0NXxjNjBIYznjN3wxMzE1NTQ2MjU5fGNho" +

java中多线程下载

package com.download; import java.io.File; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; public class MutileThreadDown { private static int blockCount=3; private static int blockS

Java多线程下载器FileDownloader(支持断点续传、代理等功能)

前言 在我的任务清单中,很早就有了一个文件下载器,但一直忙着没空去写.最近刚好放假,便抽了些时间完成了下文中的这个下载器. 介绍 同样的,还是先上效果图吧. Jar包地址位于 FileDownloader 目前实现的主要功能有: 多线程下载 断点续传 自定义头部等 即将完成的包括: 添加代理功能 ... 感觉做了回标题党,代理功能由于时间关系,将在下次更新加入. 关于设置代理,我这篇文章 Java实现Ip代理池 中有具体的设置方法. 另外除了这个代理功能,我也实在不知道下载器能加些啥功能了..

JAVA 多线程下载及断点续传

断点续传和多线程下载原理是一样的; 关键代码关键位置:即设置断点 http2.setRequestProperty("RANGE","bytes="+startl+"-");//设置断点位置,向服务器请求从文件的哪个字节开始读取.osf.seek(startl);//设置本地文件从哪个字节开始写入. 如果是单线程,则首先要判断下载文件是否已经存在;如果存在则开始断点续传,方法同多线程:因为断点续传是从上次传输中断的字节开始,则首先要得到上次中断的