1. 程式人生 > >JAVA實現多線程下載

JAVA實現多線程下載

access target 創建 tle exce 文件名 技術分享 trace any

1.開啟三個下載線程;
2.開啟一個監視線程,用於查看下載進度。

技術分享圖片

完整代碼

import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
public class JavaMultiThreadDown {
    public static void main(String[] args) throws Exception {
        // 下載路徑使用的是百度網盤上文件的下載路徑
        String _下載路徑 = "https://bjbgp01.baidupcs.com/file/1d9cedae59e9042a85cb0b98b4340c9c?bkt=p3-00007b4ef6ea09a0f17a89712f670b4985c6&fid=3255250463-250528-363978972781448&time=1554510897&sign=FDTAXGERQBHSKfW-DCb740ccc5511e5e8fedcff06b081203-1Sm5YGIZMjBwhUyJY4n2UBJLkJ0%3D&to=75&size=5528379&sta_dx=5528379&sta_cs=0&sta_ft=pdf&sta_ct=0&sta_mt=0&fm2=MH%2CQingdao%2CAnywhere%2C%2Chubei%2Cpbs&ctime=1554510826&mtime=1554510826&resv0=cdnback&resv1=0&vuk=3255250463&iv=2&htype=&newver=1&newfm=1&secfm=1&flow_ver=3&pkey=00007b4ef6ea09a0f17a89712f670b4985c6&expires=8h&rt=sh&r=458234945&mlogid=2211612084113124362&vbdid=1929586120&fin=%E4%B8%8B%E8%BD%BD%E6%B5%8B%E8%AF%95.pdf&fn=%E4%B8%8B%E8%BD%BD%E6%B5%8B%E8%AF%95.pdf&rtype=1&dp-logid=2211612084113124362&dp-callid=0.1.1&hps=1&tsl=0&csl=0&csign=4j3EXxSQdY9W8SenN6CIXXqjvfE%3D&so=0&ut=1&uter=4&serv=0&uc=4192912830&ti=90e00819b6f54250603b4062c17fc35df0cc8c47b8fc9467&by=themis";
        String _本地文件 = "有那種網站嘛?有,還是合集哦.pdf";
        int _線程數量 = 3;
        // 初始化DownUtil對象
        final Downloader downLoader = new Downloader(_下載路徑, _本地文件, _線程數量);
        // 開始下載
        downLoader.download();
    }
}
class Downloader {
    private String netUrl;// 下載資源的路徑
    private String saveFile;// 下載的路徑(含文件名)
    private int threadNum;// 線程數量
    private DownLoaderThread[] threads;// 線程數組
    private int fileSize;// 下載的文件的Size
    public Downloader(String netUrl, String targetFile, int threadNum) {
        this.netUrl = netUrl;
        this.saveFile = targetFile;
        this.threadNum = threadNum;
        // 初始化線程數組
        this.threads = new DownLoaderThread[threadNum];
    }
    public void download() throws Exception {
        URL url = new URL(netUrl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(5 * 1000);
        conn.setRequestMethod("GET");
        fileSize = conn.getContentLength();
        System.out.println("待下載文件的大小為:" + (double) (fileSize / 1024) / 1024 + "M");
        conn.disconnect();
        // 分部下載
        int currentPartSize = fileSize / threadNum + 1;
        RandomAccessFile file = new RandomAccessFile(saveFile, "rw");
        // 設置本地文件大小
        file.setLength(fileSize);
        file.close();
        // 開啟下載線程
        for (int i = 0; i < threadNum; i++) {
            // 計算每條線程的下載的開始位置
            int startPos = i * currentPartSize;
            // 每個線程使用一個RandomAccessFile進行下載
            RandomAccessFile currentPart = new RandomAccessFile(saveFile, "rw");
            // 定位線程的下載位置
            currentPart.seek(startPos);
            // 創建下載線程
            threads[i] = new DownLoaderThread(startPos, currentPartSize, currentPart);
            // 啟動下載線程
            threads[i].start();
        }
        Thread overseer = new Thread(new Overseer(this));
        overseer.start();
    }
    private class DownLoaderThread extends Thread {
        private int startPos;// 當前線程的下載位置
        private int currentPartSize;// 當前線程負責下載的文件大小
        private RandomAccessFile currentPart;// 當前線程需要下載的文件塊
        public int length;// 該線程已下載的字節數
        public DownLoaderThread(int startPos, int currentPartSize, RandomAccessFile currentPart) {
            this.startPos = startPos;
            this.currentPartSize = currentPartSize;
            this.currentPart = currentPart;
        }
        @Override
        public void run() {
            try {
                URL url = new URL(netUrl);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setConnectTimeout(5 * 1000);
                conn.setRequestMethod("GET");
                InputStream inStream = conn.getInputStream();
                // 跳過不需要下載的部分
                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();
            }
        }
    }
    private class Overseer implements Runnable {
        Downloader downLoader;
        Overseer(Downloader downLoader) {
            this.downLoader = downLoader;
        }
        @Override
        public void run() {
            double p;
            while ((p = getCompleteRate()) < 100) {
                // 隔段時間查詢一次任務完成進度,
                System.out.println("已完成:" + p + "%");
                try {
                    Thread.sleep(1500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("下載完畢");
        }
        // 獲取下載的完成百分比
        private double getCompleteRate() {
            // 統計多條線程已經下載的總大小
            int sumSize = 0;
            for (int i = 0; i < threadNum; i++) {
                sumSize += threads[i].length;
            }
            // 返回已經完成的百分比
            int percent = (int) (sumSize * 100.0 / fileSize);
            return percent;
        }
    }
}

運行結果

待下載文件的大小為:5.271484375M
已完成:0.0%
已完成:3.0%
已完成:13.0%
已完成:21.0%
已完成:29.0%
已完成:33.0%
已完成:35.0%
已完成:50.0%
已完成:64.0%
已完成:66.0%
已完成:66.0%
已完成:66.0%
已完成:66.0%
已完成:66.0%
已完成:73.0%
已完成:90.0%
下載完畢

JAVA實現多線程下載