中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

Java之多線程斷點下載的實現

2018-07-20    來源:open-open

容器云強勢上線!快速搭建集群,上萬Linux鏡像隨意使用

RandomAccessFile類:
此類的實例支持對隨機訪問文件的讀取和寫入。隨機訪問文件的行為類似存儲在文件系統(tǒng)中的一個大型 byte 數組。存在指向該隱含數組,光標或索引,稱為文件指針;輸入操作從文件指針開始讀取字節(jié),并隨著對字節(jié)的讀取而前移此文件指針。如果隨機訪問文件以讀取/ 寫入模式創(chuàng)建,則輸出操作也可用;輸出操作從文件指針開始寫入字節(jié),并隨著對字節(jié)的寫入而前移此文件指針。寫入隱含數組的當前末尾之后的輸出操作導致該數 組擴展。該文件指針可以通過 getFilePointer 方法讀取,并通過 seek 方法設置。

下面有RandomAccessFile實現安卓下的斷點下載的demo。
服務器端可以用tomcat模擬,將被下載的測試文件放入webApp/ROOT目錄下即可。
先給出java借助HttpURLConnection類實現的多線程下載代碼:

public class MultiThread {
    private static int threadCount = 3;
    private static long blockSize;
    private static int runningThreadCount;
    public static void main(String[] args) throws Exception {
        String path = "http://10.0.67.172/test.exe";
        URL url = new URL(path); 
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(5000);//超時時間
        int code = conn.getResponseCode();
        System.out.println(code);

        if(code / 100 == 2){
            int size = conn.getContentLength();//獲取資源文件的長度
            System.out.println("請求資源大小:" + size);
            blockSize = size / threadCount;//將資源文件分為多少塊,沒一塊的大小

            runningThreadCount = threadCount;
            long startIndex = 0;
            long endIndex = 0;
            //開啟若干個子線程去實現多線程的下載
            for(int i = 0; i < threadCount; i++){
                startIndex = i * blockSize;
                endIndex = (i + 1) * blockSize - 1;
                if(i == threadCount-1){
                    endIndex = size - 1;
                }
                System.out.println("開啟線程:" + i + ";" + "開始位置:" + startIndex + ":" + "結束位置:" + endIndex);
                new DownThread(path, startIndex, endIndex, i).start();
            }
        }
    }

    private static class DownThread extends Thread{
        private String path;
        private long startIndex;
        private long endIndex;
        private int threadId;

        public DownThread(String path, long startIndex, long endIndex, int threadId) {
            super();
            this.path = path;
            this.startIndex = startIndex;
            this.endIndex = endIndex;
            this.threadId = threadId;
        }

        @Override
        public void run() {
            try {
                URL url = new URL(path);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                conn.setReadTimeout(5000);
                conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);//設置服務器上的文件的讀取位置

                int code = conn.getResponseCode();
                if(code / 100 == 2){
                    InputStream is = conn.getInputStream();
                    File file = new File("temp.exe");
                    RandomAccessFile raf = new RandomAccessFile(file, "rw");
                    raf.seek(startIndex);
                    System.out.println("第" + threadId + "個文件的開始位置:" + String.valueOf(startIndex));
                    int len = 0;
                    byte[] buffer = new byte[1024];
                    while ((len = is.read(buffer)) != -1){
                        raf.write(buffer, 0, len);//寫文件
                    }
                    raf.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

斷點下載的原理就是將上次文件下載的位置保存為臨時文件,當完全下載完畢時再刪除。

public class MultiThread {
    private static int threadCount = 3;
    private static long blockSize;
    private static int runningThreadCount;
    public static void main(String[] args) throws Exception {
        String path = "http://10.0.67.172/test.rar";
        URL url = new URL(path); 
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(5000);//超時時間
        int code = conn.getResponseCode();
        System.out.println(code);

        if(code / 100 == 2){
            int size = conn.getContentLength();//獲取資源文件的長度
            System.out.println("請求資源大小:" + size);
            blockSize = size / threadCount;//將資源文件分為多少塊,沒一塊的大小

            runningThreadCount = threadCount;
            long startIndex = 0;
            long endIndex = 0;
            for(int i = 0; i < threadCount; i++){
                startIndex = i * blockSize;
                endIndex = (i + 1) * blockSize - 1;
                if(i == threadCount-1){
                    endIndex = size - 1;
                }
                System.out.println("開啟線程:" + i + ";" + "開始位置:" + startIndex + ":" + "結束位置:" + endIndex);
                new DownThread(path, startIndex, endIndex, i).start();
            }
        }
    }

    private static class DownThread extends Thread{
        private String path;
        private long startIndex;
        private long endIndex;
        private int threadId;

        public DownThread(String path, long startIndex, long endIndex, int threadId) {
            super();
            this.path = path;
            this.startIndex = startIndex;
            this.endIndex = endIndex;
            this.threadId = threadId;
        }

        @Override
        public void run() {
            int total = 0;
            try {
                File positionFile = new File(threadId + ".txt");

                URL url = new URL(path);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                //接著上次的文件繼續(xù)下載
                if(positionFile.exists() && positionFile.length() > 0){
                    FileInputStream fis = new FileInputStream(positionFile);
                    BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
                    //獲取當前線程上次下載的總大小是多少
                    String lasttotalstr = reader.readLine();
                    int lastTotal = Integer.valueOf(lasttotalstr);
                    System.out.println("上次線程下載的總大小:" + lastTotal);
                    startIndex += lastTotal;
                    total += lastTotal;
                    fis.close();
                }
                conn.setReadTimeout(5000);
                conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);//設置服務器上的文件的讀取位置

                int code = conn.getResponseCode();
                if(code / 100 == 2){
                    InputStream is = conn.getInputStream();
                    File file = new File("temp.rar");
                    RandomAccessFile raf = new RandomAccessFile(file, "rw");
                    raf.seek(startIndex);
                    System.out.println("第" + threadId + "個文件的開始位置:" + String.valueOf(startIndex));
                    int len = 0;
                    byte[] buffer = new byte[1024];
                    while ((len = is.read(buffer)) != -1){
                        RandomAccessFile rf = new RandomAccessFile(positionFile, "rwd");
                        raf.write(buffer, 0, len);//寫文件
                        total += len;
                        rf.write(String.valueOf(total).getBytes());
                        rf.close();
                    }
                    is.close();
                    raf.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
                synchronized (DownThread.class) {
                    System.out.println("線程" + threadId + "下載完畢了");
                    runningThreadCount--;
                    if (runningThreadCount < 1) {
                        System.out.println("所有的線程都工作完畢了。刪除臨時記錄的文件");
                        for (int i = 0; i < threadCount; i++) {
                            File f = new File(i + ".txt");
                            System.out.println(f.delete());
                        }
                    }
                }
            }
        }
    }
}

標簽: 代碼 服務器 服務器端

版權申明:本站文章部分自網絡,如有侵權,請聯系:west999com@outlook.com
特別注意:本站所有轉載文章言論不代表本站觀點!
本站所提供的圖片等素材,版權歸原作者所有,如需使用,請與原作者聯系。

上一篇:PHP 調用 MySQL 存儲過程并獲得返回值

下一篇:列出目錄中的所有子目錄的PHP函數