欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

视频图片--多线程下载工具

程序员文章站 2022-07-11 11:18:13
还嫌网速慢? 那是因为你没有一个好的下载工具, 多线程下载, 线程个数自己定义, 想多块就多快,一起来看看吧!!! 多线程使用线程计数同步辅助,同步计算多线程个数,如果线程下载超时, 支持重新下载,方便使用. 1.多线程工具类: MutiThreadDownLoad.java 2.封装工具类方法: ......

还嫌网速慢? 那是因为你没有一个好的下载工具, 多线程下载, 线程个数自己定义, 想多块就多快,一起来看看吧!!!

多线程使用线程计数同步辅助,同步计算多线程个数,如果线程下载超时, 支持重新下载,方便使用.

 

 

 

 

1.多线程工具类:   mutithreaddownload.java

 

import java.io.inputstream;
import java.io.randomaccessfile;
import java.net.httpurlconnection;
import java.net.url;
import java.text.simpledateformat;
import java.util.date;
import java.util.concurrent.countdownlatch;

public class mutithreaddownload {
    // 同时下载的线程数
    private int threadcount;
    // 服务器请求路径
    private string serverpath;
    //记录下载完成的次数
    public static int number_thread=50;
    //本地路径
    private string localpath;
    //线程计数同步辅助
    private countdownlatch latch;
 
    public mutithreaddownload(int threadcount, string serverpath, string localpath, countdownlatch latch) {
        this.number_thread=threadcount;
        this.threadcount = threadcount;
        this.serverpath = serverpath;
        this.localpath = localpath;
        this.latch = latch;
    }

 
    public boolean executedownload() {
        try {
            url url = new url(serverpath);
            httpurlconnection conn = (httpurlconnection) url.openconnection();
            conn.setconnecttimeout(5000);
            conn.setrequestmethod("get");
            int code = conn.getresponsecode();
            if (code == 200) {
                //服务器返回的数据的长度,实际上就是文件的长度,单位是字节
                int length = conn.getcontentlength();
                system.out.println("文件总长度:" + length + "字节(b)");
                if (length == 0) {
                    return false;
                }

                randomaccessfile raf = new randomaccessfile(localpath, "rwd");
                //指定创建的文件的长度
                raf.setlength(length);
                raf.close();
                //分割文件
                int blocksize = length / threadcount;
                for (int threadid = 1; threadid <= threadcount; threadid++) {
                    //第一个线程下载的开始位置
                    int startindex = (threadid - 1) * blocksize;
                    int endindex = startindex + blocksize - 1;
                    if (threadid == threadcount) {
                        //最后一个线程下载的长度稍微长一点
                        endindex = length;
                    }

                    system.out.println("线程" + threadid + "下载:" + startindex + "字节~" + endindex + "字节");
                    new downloadthread(threadid, startindex, endindex).start();
                }
            }
        } catch (exception e) {
            e.printstacktrace();
        }
      return true;
    }


    /**

     * 内部类用于实现下载

     */

    public class downloadthread extends thread {
        //线程id
        private int threadid;
        //下载起始位置
        private int startindex;
        //下载结束位置
        private int endindex;

        public downloadthread(int threadid, int startindex, int endindex) {
            this.threadid = threadid;
            this.startindex = startindex;
            this.endindex = endindex;
        }

        @override
        public void run() {
            down_time();
        }

 

        /**

         * 如果超时,或者下载失败,就使用递归重新下载

         */

        public void down_time(){
            try {
                system.out.println("线程" + threadid + "正在下载...");
                url url = new url(serverpath);
                httpurlconnection conn = (httpurlconnection) url.openconnection();
                conn.setrequestmethod("get");
                //请求服务器下载部分的文件的指定位置
                conn.setrequestproperty("range", "bytes=" + startindex + "-" + endindex);
                conn.setconnecttimeout(10000);
                conn.setreadtimeout(10000);
                int code = conn.getresponsecode();
                system.out.println("线程" + threadid + "请求返回code=" + code);
                inputstream is = conn.getinputstream();//返回资源
                randomaccessfile raf = new randomaccessfile(localpath, "rwd");
                //随机写文件的时候从哪个位置开始写
                raf.seek(startindex);//定位文件
                int len = 0;
                byte[] buffer = new byte[1024];
                while ((len = is.read(buffer)) != -1) {
                    raf.write(buffer, 0, len);
                }
                is.close();
                raf.close();
                number_thread=number_thread-1;
                system.out.println("线程" + threadid + "下载完毕  "+number_thread);
                //计数值减一
                latch.countdown();
            } catch (exception e) {
                system.out.println(new simpledateformat("yyyy-mm-dd hh:mm:ss aa").format(new date())+":线程 "+threadid + "访问超时,重新下载!!");
                down_time();
            }
        }
    }
}

 

 

 

2.封装工具类方法:

   public static boolean download(string remoteurl,string localurl){
    boolean bd=true;
    int threadsize = 50;
    string serverpath = remoteurl;
    string localpath = localurl;
    long starttime = system.currenttimemillis();
    countdownlatch latch = new countdownlatch(threadsize);
    mutithreaddownload m = new mutithreaddownload(threadsize, serverpath, localpath, latch);
    try {
        boolean x = m.executedownload();
        //如果文件的长度等于0,则直接跳过等待,不提示错误
        if (x){
            latch.await();
        }else{
            bd=false;//下载失败
        }
    } catch (interruptedexception e) {
        e.printstacktrace();
    }

    long endtime = system.currenttimemillis();
    system.out.println("全部下载结束,共耗时" + (endtime - starttime) / 1000 + "s");
    return bd;
}

 

 

3.使用示例:

string urlss="";//要下载的网络资源路径

string urltt="";//要存放的本地路径

download(urlss,urltt);