JAVA实现简单的多线程下载工具

JAVA实现简单的多线程下载工具

  • 包和类
    在这里插入图片描述
  • DownUtil类
package MulThreadUtil;

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

public class DownUtil {
    
    
    //定义下载资源的路径
    private String path;
    //指定所下载文件的保存位置
    private String targetFile;
    //指定需要使用多少个线程下载资源
    private int threadNum;
    //定义下载的线程对象
    private DownThread[] threads;
    //定义下载的文件的总大小
    private int fileSize;

    public DownUtil(String path,String targetFile,int threadNum){
    
    
        this.path=path;
        this.threadNum=threadNum;
        //初始化threads数组
        threads=new DownThread[threadNum];
        this.targetFile=targetFile;
    }

    public void download() throws Exception
    {
    
    
        URL url=new URL(path);
        HttpURLConnection conn=(HttpURLConnection)url.openConnection();
        conn.setConnectTimeout(5*1000);
        conn.setRequestMethod("GET");
        conn.setRequestProperty(
                "Accept",
                "image/gif,image/jpeg,image/pjpeg,"
                +"application/x-shockwave-flash,application/xaml+xml,"
                +"application/vnd.ms-xpsdocument,application/x-ms-xbap,"
                +"application/x-ms-application,application/vnd.ms-excel,"
                +"application/vnd.ms-powerpoint,application/msword, */*"
        );
        conn.setRequestProperty("Accept-Language","zh-CN");
        conn.setRequestProperty("Charset","UTF-8");
        conn.setRequestProperty("Connection","Keep-Alive");
        //上述代码为设置请求头

        //得到文件大小
        fileSize=conn.getContentLength();
        conn.disconnect();
        int currentPartSize=fileSize/threadNum+1;
        RandomAccessFile file=new RandomAccessFile(targetFile,"rw");//以读写方式打开指定文件,若文件不存在,尝试创建该文件
        //设置本地文件的大小
        file.setLength(fileSize);
        file.close();
        for (int i=0;i<threadNum;i++){
    
    
            //计算每个线程下载的开始位置
            int startPos=i*currentPartSize;
            //每个线程使用一个RandomAccessFile进行下载
            RandomAccessFile currentPart=new RandomAccessFile(targetFile,"rw");
            //定位该线程的下载位置
            currentPart.seek(startPos);
            //创建下载线程
            threads[i]=new DownThread(startPos,currentPartSize,currentPart);
            //启动下载线程
            threads[i].start();
        }
    }

    //获取下载的完成百分比
    public double getCompleteRate(){
    
    
        //统计多个线程已经下载的总大小
        int sumSize=0;
        for (int i=0;i<threadNum;i++){
    
    
            sumSize=sumSize+threads[i].length;
        }
        //返回已经完成的百分比
        return sumSize*1.0/fileSize;
    }

    private class DownThread extends Thread{
    
    
        //当前线程的下载位置
        private int startPos;
        //定义当前线程负责下载的文件大小
        private int currentPartSize;
        //当前线程需要下载的文件块
        private RandomAccessFile currentPart;
        //定义该线程已经下载的字节数
        public int length;

        public DownThread(int startPos,int currentPartSize,RandomAccessFile currentPart){
    
    
            this.startPos=startPos;
            this.currentPartSize=currentPartSize;
            this.currentPart=currentPart;
        }

        public void run(){
    
    
            try
            {
    
    
                URL url=new URL(path);
                HttpURLConnection conn=(HttpURLConnection)url.openConnection();
                conn.setConnectTimeout(5*1000);
                conn.setRequestMethod("GET");
                conn.setRequestProperty(
                        "Accept",
                        "image/gif,image/jpeg,image/pjpeg,"
                                +"application/x-shockwave-flash,application/xaml+xml,"
                                +"application/vnd.ms-xpsdocument,application/x-ms-xbap,"
                                +"application/x-ms-application,application/vnd.ms-excel,"
                                +"application/vnd.ms-powerpoint,application/msword, */*"
                );
                conn.setRequestProperty("Accept-Language","zh-CN");
                conn.setRequestProperty("Charset","UTF-8");
                InputStream inStream=conn.getInputStream();//
                //跳过startPos个字节,表明线程只下载自己负责的那部分文件
                inStream.skip(this.startPos);
                byte[] buffer=new byte[1024];
                int hasRead=0;
                //读取网络数据并写入本地文档
                while(length<currentPartSize&&(hasRead=inStream.read(buffer))!=-1){
    
    
                    currentPart.write(buffer,0,hasRead);
                    //累计线程下载的总大小
                    length +=hasRead;
                }
                currentPart.close();
                inStream.close();
            } catch (Exception e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

  • MultiThreadDown类
package MulThreadUtil;

public class MultiThreadDown {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //初始化DownUtil对象
        final DownUtil downUtil=new DownUtil("https://www.baidu.com/img/bd_logo1.png","xu.png",4);
        //开始下载
        downUtil.download();
        new Thread(()->{
    
    
            while (downUtil.getCompleteRate()<1){
    
    
                //每隔0.1秒查询一次任务的完成进度
                System.out.println("已完成:"+downUtil.getCompleteRate());
                try {
    
    
                    Thread.sleep(10);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
        ).start();
    }
}

运行结果:在这里插入图片描述
在该程序的路径下,得到了一个名为xu.png的图片
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45821324/article/details/109700041
今日推荐