Android 多线程断点下载

  1. 多线程下载
    public class MultiThreadDownloader {
    
        private URL url;        // 目标地址
        private File file;        // 本地文件
        private long threadLen;    // 每个线程下载多少
    
        private static final int THREAD_AMOUNT = 3;                // 线程数
        private static final String DIR_PATH = "F:/Download";    // 下载目录
    
        public MultiThreadDownloader(String address) throws IOException {    
            // 记住下载地址
            url = new URL(address);                                                            
            // 截取地址中的文件名, 创建本地文件
            file = new File(DIR_PATH, address.substring(address.lastIndexOf("/") + 1));        
        }
    
        public void download() throws IOException {
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(3000);
    
            // 获取文件总长度
            long totalLen = conn.getContentLength();                    
            // 计算每个线程要下载的长度
            // 总长度 如果能整除 线程数, 每条线程下载的长度就是 总长度 / 线程数
            // 总长度 如果不能整除 线程数, 那么每条线程下载长度就是 总长度 / 线程数 + 1
            threadLen = (totalLen + THREAD_AMOUNT - 1) / THREAD_AMOUNT;    
    
            // 在本地创建一个和服务端大小相同的文件
            RandomAccessFile raf = new RandomAccessFile(file, "rw");    
            // 设置文件的大小, 写入了若干个0
            raf.setLength(totalLen);                                    
            raf.close();
    
            // 按照线程数循环
            for (int i = 0; i < THREAD_AMOUNT; i++) {
                // 开启线程, 每个线程将会下载一部分数据到本地文件中 
                new DownloadThread(i).start();       
            }     
        }
    
        private class DownloadThread extends Thread {
            // 用来标记当前线程是下载任务中的第几个线程
            private int id;     
    
            public DownloadThread(int id) {
                this.id = id;
            }
    
            public void run() {
                // 从临时文件读取当前线程已完成的进度
    
                long start = id * threadLen;     
                long end = id * threadLen + threadLen - 1;
                System.out.println("线程" + id + ": " + start + "-" + end);
    
                try {
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setConnectTimeout(3000);
                    // 设置当前线程下载的范围(start和end都包含)
                    conn.setRequestProperty("Range", "bytes=" + start + "-" + end);    
    
                    InputStream in = conn.getInputStream();
                    // 随机读写文件, 用来向本地文件写出
                    RandomAccessFile raf = new RandomAccessFile(file, "rw");        
                    // 设置保存数据的位置
                    raf.seek(start);                                                
    
                    // 每次拷贝100KB
                    byte[] buffer = new byte[1024 * 100];    
                    int len;
                    while ((len = in.read(buffer)) != -1) {
                        // 从服务端读取数据, 写到本地文件
                        raf.write(buffer, 0, len);            
                    }
                    raf.close();
    
                    System.out.println("线程" + id + "下载完毕");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        public static void main(String[] args) throws IOException {
            new MultiThreadDownloader("http://192.168.1.240:8080/14.Web/android-sdk_r17-windows.zip").download();
        }
    }
    
  2. 断点下载
    public class BreakpointDownloader {
        // 下载目录
        private static final String DIR_PATH = "F:/Download";    
        // 总线程数
        private static final int THREAD_AMOUNT = 3;                
    
        // 目标下载地址
        private URL url;            
        // 本地文件
        private File dataFile;        
        // 用来存储每个线程下载的进度的临时文件
        private File tempFile;        
        // 每个线程要下载的长度
        private long threadLen;      
        // 总共完成了多少  
        private long totalFinish;    
        // 服务端文件总长度
        private long totalLen;        
        // 用来记录开始下载时的时间
        private long begin;            
    
        public BreakpointDownloader(String address) throws IOException {    
            url = new URL(address);                                                            
            dataFile = new File(DIR_PATH, address.substring(address.lastIndexOf("/") + 1));    
            tempFile = new File(dataFile.getAbsolutePath() + ".temp");                        
        }
    
        public void download() throws IOException {
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(3000);
    
            totalLen = conn.getContentLength();                                    
            threadLen = (totalLen + THREAD_AMOUNT - 1) / THREAD_AMOUNT;            
    
            if (!dataFile.exists()) {                                            
                RandomAccessFile raf = new RandomAccessFile(dataFile, "rws");    
                raf.setLength(totalLen);                                        
                raf.close();
            }
    
            if (!tempFile.exists()) {                                            
                RandomAccessFile raf = new RandomAccessFile(tempFile, "rws");    
                for (int i = 0; i < THREAD_AMOUNT; i++)                           
                    raf.writeLong(0);                                            
                raf.close();
            }
    
            for (int i = 0; i < THREAD_AMOUNT; i++) { 
                new DownloadThread(i).start();       
            } 
    
            // 记录开始时间
            begin = System.currentTimeMillis();        
        }
    
        private class DownloadThread extends Thread {
            // 用来标记当前线程是下载任务中的第几个线程
            private int id;     
    
            public DownloadThread(int id) {
                this.id = id;
            }
    
            public void run() {
                try {
                    RandomAccessFile tempRaf = new RandomAccessFile(tempFile, "rws");        
                    tempRaf.seek(id * 8);                        
                    long threadFinish = tempRaf.readLong();        
                    synchronized(BreakpointDownloader.this) {    
                        totalFinish += threadFinish;            
                    }
    
                    long start = id * threadLen + threadFinish;      
                    long end = id * threadLen + threadLen - 1;       
                    System.out.println("线程" + id + ": " + start + "-" + end);
    
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setConnectTimeout(3000);
                    conn.setRequestProperty("Range", "bytes=" + start + "-" + end);        
    
                    InputStream in = conn.getInputStream();                              
                    RandomAccessFile dataRaf = new RandomAccessFile(dataFile, "rws");    
                    dataRaf.seek(start);                                                
    
                    byte[] buffer = new byte[1024 * 100];            
                    int len;
                    while ((len = in.read(buffer)) != -1) {
                        dataRaf.write(buffer, 0, len);               
                        threadFinish += len;                        
                        tempRaf.seek(id * 8);                        
                        tempRaf.writeLong(threadFinish);           
                        synchronized(BreakpointDownloader.this) {   
                            totalFinish += len;                        
                        }
                    }
                    dataRaf.close();
                    tempRaf.close();
    
                    System.out.println("线程" + id + "下载完毕");
                    // 如果已完成长度等于服务端文件长度(代表下载完成)
                    if (totalFinish == totalLen) {                    
                        System.out.println("下载完成, 耗时: " + (System.currentTimeMillis() - begin));
                        // 删除临时文件
                        tempFile.delete();                            
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        public static void main(String[] args) throws IOException {
            new BreakpointDownloader("http://192.168.1.240:8080/14.Web/android-sdk_r17-windows.zip").download();
        }
    }
    

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程