多线程下载工具

本文出自:《疯狂java讲义第3版本》第十七章

下载url文件,并不是线程越多,下载的越快,一定是有一个最佳的方案。
测试经过:path为20M的MP3文件 , 用1个线程用时:13197ms;用2个线程用时8560ms;用3个线程用时:13894ms;用4个线程用时16648ms;
具体还是要根据项目环境做选择。

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;

/**
 * 多线程下载工具
 */
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.targetFile = targetFile;
        this.threadNum = threadNum;
        threads = new DownThread[threadNum];
    }

    public void download() throws IOException {
        URL url = new URL(path);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(5 * 1000);
        conn.setRequestMethod("GET");
        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 += threads[i].length;
        }
        return sumSize * 1.0 / fileSize;
    }

    private class DownThread extends Thread {

        private int startPos;                   //当前线程的下载位置
        private int currentPartSize;            //当前线程需要负责的大小
        private RandomAccessFile currentPart;   //当前线程需要下载的文件块
        private 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");
                InputStream in = conn.getInputStream();
                BufferedInputStream bis = new BufferedInputStream(in);
                bis.skip(startPos);
                byte[] buff = new byte[1024];
                int hasRead = 0;
                while (length < currentPartSize && (hasRead = bis.read(buff)) != -1) {
                    currentPart.write(buff, 0, hasRead);
                    length += hasRead;
                }
                currentPart.close();
                bis.close();
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws IOException {
        DownUtil downUtil = new DownUtil("http://www.ytmp3.cn/down/57196.mp3", "G:/57196.mp3", 2);
        long start = new Date().getTime();
        downUtil.download();

        new Thread(() -> {
            while (downUtil.getCompleteRate() < 1) {
                long end = new Date().getTime();
                System.out.println("已完成:"+(end -start) +"ms"+ downUtil.getCompleteRate());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

猜你喜欢

转载自www.cnblogs.com/Uzai/p/10295855.html