JavaSE多线程下载的实现

本文中主要提供的是java多线程下载文件方案,以及java多线程将临时进度保存到文件,多线程断点续传的实现;

1、多线程下载

2、将下载进度保存到临时文件,多线程的断定续传


1、多线程下载

本例中首先在Tomcat服务器中的WEBAPP/ROOT/文件夹下面放置了SoftwareOffer.exe的二进制可执行文件,如果放置图片的话,中间数据如果出错,不容易用肉眼识别,但是如果是二进制文件的话,如果中间任何二进制的一位数据出错,必然造成二进制可执行文件无法运行!所以测试选择二进制可执行文件比较妥当!

代码如下:


  • MultiDownloader.java
import java.net.HttpURLConnection;
import java.net.URL;
/**
 * 多线程下载器
 * @author YQ
 */
public class MultiDownloader {

    //总线程数
    private final static int totalThreadCount = 3;

    @SuppressWarnings("unused")
    public static void main(String[] args) throws Exception {
        System.out.println("多线程下载器");
        URL url = new URL("http://192.168.1.102:8080/SoftwareOffer.exe");
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        int code = conn.getResponseCode();
        if(code == 200) {
            int length = conn.getContentLength();
            System.out.println("服务器资源文件长度:"+length);
            int blockSize = length / 3;//服务器资源等分为三份,每一份的大小相同
            System.out.println("资源文件每一份的到小:"+blockSize);

            for(int threadid = 0;threadid < totalThreadCount;threadid++) {
                int startPosition = threadid * blockSize;
                int endPosition = (threadid+1) * blockSize - 1;

                if(threadid == (totalThreadCount - 1)) {
                    endPosition = length - 1;
                }
                System.out.println("线程:" + threadid + "下载范围:" + startPosition + "~" + endPosition);

                byte[] buffer = new byte[blockSize];
            }

        }
    }

}

2、将下载进度保存到临时文件,多线程的断定续传

本例中同样在Tomcat服务器中的WEBAPP/ROOT/文件夹下面放置了SoftwareOffer.exe的二进制可执行文件;


  • DemoDownLoad.java
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * 将下载进度保存到临时文件
 * 多线程的断定续传
 * @author YQ
 *
 */

public class DemoDownLoad {
    static String path = "http://192.168.1.102:8080/SoftwareOffer.exe";
    static int threadCount = 3;
    static int finishedThread = 0;
    public static void main(String[] args) {
        //发送http请求,拿到目标文件的长度
        try {
            URL url = new URL(path);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(8000);
            conn.setReadTimeout(8000);

            if(conn.getResponseCode() == 200) {
                //获取长度
                int length = conn.getContentLength();//算出进程的开始位置和结束位置

                //创建临时文件
                File file = new File(getNameFormPath(path));
                //临时文件的使用
                RandomAccessFile raf = new RandomAccessFile(file,"rwd");
                //设置临时文件的大小与目标文件相互一致
                raf.setLength(length);
                raf.close();
                //计算每一个线程下载的区间
                int size = length / threadCount;

                for (int id=0;id < threadCount;id++) {
                    int startIndex = id * size;
                    int endIndex = (id + 1) * size - 1;
                    if(id == threadCount - 1) {
                        endIndex = length - 1;
                    }
                    System.out.println("线程" + id + "下载区间" + startIndex + "-" + endIndex);
                    new DownLoadThread(id, startIndex, endIndex).start();
                }
            }
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static String getNameFormPath(String path) {
        int index = path.lastIndexOf("/");
        return path.substring(index + 1);
    }
}

class DownLoadThread extends Thread {

    int threadId;
    int startIndex;
    int endIndex;

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

    @Override
    public void run() {
        //发送Http请求,三次下载则是需要三次下载请求
        try {
            File fileProgress = new File(threadId+".txt");
            int lastProgress = 0;
            if(fileProgress.exists()) {
                //读取进度临时文件中内容
                FileInputStream fis = new FileInputStream(fileProgress);
                BufferedReader br = new BufferedReader(new InputStreamReader(fis));
                //得到上一次的下载进度数据
                lastProgress = Integer.parseInt(br.readLine());
                //改变下载开始位置,上一次下过的文件,这一次就不再进行请求
                startIndex += lastProgress;
                //进度临时文件的输入流必须关闭
                fis.close();
            }

            URL url = new URL(DemoDownLoad.path);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(8000);
            conn.setReadTimeout(8000);

            //设置请求数据的区间
            conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);

            //请求部分数据成功的响应码是206
            if(conn.getResponseCode() == 206) {
                InputStream is = conn.getInputStream();
                byte[] bytes = new byte[1024];
                int len = 0;
                File file = new File(DemoDownLoad.getNameFormPath(DemoDownLoad.path));
                RandomAccessFile raf = new RandomAccessFile(file, "rwd");
                //设置写入文件的开始位置
                raf.seek(startIndex);
                //当前线程下载的总进度
                int total = lastProgress;
                while((len = is.read(bytes)) != -1) {
                    raf.write(bytes,0,len);
                    total += len;
                    System.out.println("线程"+threadId+"下载了:"+total);
                    //创建一个文本临时文件,保存下载进度
                    RandomAccessFile rafProgress = new RandomAccessFile(fileProgress, "rwd");
                    //每次下载1024个字节,就马上把1024写入文本的临时文件
                    rafProgress.write((total+"").getBytes());
                    rafProgress.close();
                }
                raf.close();
                System.out.println("线程"+threadId+"下载完成");

                DemoDownLoad.finishedThread++;
                //首先必须要保证三条线程全部都下载完毕才可以删除
                synchronized (DemoDownLoad.path) {
                    if(DemoDownLoad.finishedThread == 3) {
                        //可能会出现线程不安全
                        for (int i=0;i<DemoDownLoad.finishedThread;i++) {
                            File f = new File(i+".txt");
                            f.delete();
                        }
                        DemoDownLoad.finishedThread = 0;
                    }
                }
            }

        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
时间: 2024-10-04 17:01:17

JavaSE多线程下载的实现的相关文章

linux下多线程下载工具axel的编译安装

axel 是Linux 命令行下多线程的下载工具,支持断点续传,速度通常情况下是Wget的几倍 官方主页:http://axel.alioth.debian.org/ 源码下载: #curl -O http://pkgs.fedoraproject.org/repo/pkgs/axel/axel2.4.tar.gz/a2a762fce0c96781965c8f9786a3d09d/axel-2.4.tar.gz 编译安装: # tar -xvf axel-2.4.tar.gz  && cd

Android 多线程下载,断点续传,线程池

你可以在这里看到这个demo的源码: https://github.com/onlynight/MultiThreadDownloader 效果图 这张效果图是同时开启三个下载任务,限制下载线程数量的效果图. 多线程下载原理 多线程下载的原理就是将下载任务分割成一个个小片段再将每个小片段分配给各个线程进行下载. 例如一个文件大小为100M,我们决定使用4个线程下载,那么每个线程下载的大小即为25M,每个线程的起始以及结束位置依次如下: 0: 0-25M 1: 25-50M 2: 50-75M 3

【幻化万千戏红尘】qianfengDay27-HttpURLConnection,OkHttpClient,,多线程下载且断点续传基础学习:

课程回顾: Servlet:java语言开发的运行在服务器上的开发步骤:1.创建Servlet类2.重写doGet或doPost方法3.运行在服务器 生命周期:1.初始化2.服务3.销毁 URL:统一资源定位符,网址openConnection 今日内容:Http协议:超文本传输协议常用方式:1.HttpURLConnection2.okHttp HttpURLConnection的使用步骤:1.创建URL对象---URL url=new URL("网址");2.获取连接对象--Htt

java多线程下载

多线程下载是通过占有服务器资源来提高速度的.每个线程应该下载一个文件的不同位置,假如现在有一个长度为10的资源,有三个线程,那么第一个线程下载的长度为012,第二个为345,第四个为6789所以问题来了每个线程下载的长度是多少呢?线程的id为0,1,2每个线程下载的数量=总长度/线程数量size=10/3start:id*sizeend:(id+1)*size-1最后一个线程的结束位置为:总长度-1 package down; import java.io.File; import java.i

J哥---------Android 多线程下载 仿下载助手(改进版)

首先声明一点: 这里的多线程下载 并不是指的 多个线程下载一个 文件,而是 每个线程 负责一个文件.真正的多线程 希望后面能给大家带来.  -------------  欢迎 爱学习的小伙伴 加群  -------------  -------------android交流群:230274309------------- -------------一起分享,一起进步!  需要你们-------------- --------------  期待各位爱学习的小伙伴们 的到来------------

Android之——多线程下载示例(一)

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46883927 一.概述 说到Android中的文件下载,Android API中明确要求将耗时的操作放到一个子线程中执行,文件的下载无疑是需要耗费时间的,所以要将文件的下载放到子线程中执行.下面,我们一起来实现一个Android中利用多线程下载文件的小例子. 二.服务端准备 在这个小例子中我以下载有道词典为例,在网上下载有道词典的安装包,在eclipse中新建项目web,将下载的

java实现多线程下载

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

无废话Android之smartimageview使用、android多线程下载、显式意图激活另外一个activity,检查网络是否可用定位到网络的位置、隐式意图激活另外一个activity、隐式意图的配置,自定义隐式意图、在不同activity之间数据传递(5)

1.smartimageview使用 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"

Android版多线程下载器核心代码分享

首先给大家分享多线程下载核心类: 1 package com.example.urltest; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.io.RandomAccessFile; 6 import java.net.HttpURLConnection; 7 import java.net.MalformedURLException; 8 import java.net.URL; 9 im