码迷,mamicode.com
首页 > 编程语言 > 详细

多线程断点续传的DEMO

时间:2015-08-17 12:19:48      阅读:188      评论:0      收藏:0      [点我收藏+]

标签:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 *    多线程断点续传的原理
 * 1、当多线程突然中断的时候,在缓存文件中保存中断的位置;
 * 2、当续传的时候,分别读取缓存文件中的位置,然后作为开始的位置下载。
 * @author Sheamus
 *
 */
public class MutilHttpDownload {
    //完成下载的线程数
    static int finishedThread = 0;
    static String path = "http://10.31.2.6:8080/demo/QQ.exe";
    static int PROCESSNUM = 3;
    
    public static void main(String[] args) {
        //请求文件的大小并创建一个一样大小的缓存文件
        try {
            URL url = new URL(path);
            //在项目的目录下创建一个QQ.exe文件
            File file = new File("QQ.exe");
            RandomAccessFile raf = new RandomAccessFile(file, "rwd");
            
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setReadTimeout(5000);
            conn.setReadTimeout(5000);
            
            if(conn.getResponseCode() == 200) {
                int length = conn.getContentLength();
                //设置缓存文件的大小
                raf.setLength(length);
                raf.close();
                //计算每个线程应该下载的大小
                int size = length / PROCESSNUM;
                //计算每个线程开始和结束的位置
                for(int i = 0; i < PROCESSNUM; i++) {
                    
                    int startIndex = i * size;
                    int endIndex = (i + 1) * size - 1;
                    //当时最后一个线程的时候,最后的位置就是总长度减1
                    if(i == (PROCESSNUM - 1)) {
                        endIndex = length - 1;
                    }
                    //启动线程执行下载
                    new SingleDownLoadThread(startIndex,endIndex,i).start();
                }
            }
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

class SingleDownLoadThread extends Thread {
    private int startIndex;
    private int endIndex;
    private int currentThreadId;
    public SingleDownLoadThread(int startIndex, int endIndex, int currentThreadId) {
        super();
        this.startIndex = startIndex;
        this.endIndex = endIndex;
        this.currentThreadId = currentThreadId;
    }
    @Override
    public String toString() {
        return "DownLoadThread [startIndex=" + startIndex + ", endIndex="
                + endIndex + ", currentThreadId=" + currentThreadId + "]";
    }
    @Override
    public void run() {
        int total = 0;
        //下载该线程的要下载的部分
        try {
            //定义缓存文件用于保存下载的位置
            File tempFile = new File("temp" + currentThreadId +".txt");
            if(tempFile.exists()) {
                //下载的时候,如果有缓存文件,读取缓存中文件,将这个数字替换开始的位置
                FileInputStream fis = new FileInputStream(tempFile);
                BufferedReader bis = new BufferedReader(new InputStreamReader(fis));
                int tempStartIndex = Integer.parseInt(bis.readLine());
                startIndex = tempStartIndex;
                fis.close();
            }
            System.out.println("下载的区间是 :" + startIndex +" -- > " + endIndex +"--------------------------------");
            File file = new File("QQ.exe");
            RandomAccessFile raf = new RandomAccessFile(file, "rwd");
            
            URL url = new URL(MutilHttpDownload.path);
            
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
            //设置要下载的部分
            conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
            //将随机读取读取文件的流的指针指向要读文件的开始位置
            raf.seek(startIndex);
            //部分文件获取成功的返回码是206
            if(conn.getResponseCode() == 206) {
                InputStream in = conn.getInputStream();
                byte[] b = new byte[1024];
                int len = 0;
                while((len = in.read(b)) != -1) {
                    raf.write(b, 0, len);
                    total += len;
                    System.out.println("线程 " + currentThreadId + "下载了 " + total);
                    //创建一个输出流写出当前读到的位置
                    RandomAccessFile tempRaf = new RandomAccessFile(tempFile, "rwd");
                    tempRaf.write((total+"").getBytes());
                    tempRaf.close();
                }
                System.out.println("线程 " + currentThreadId + "下载完成!");
                raf.close();
                
                MutilHttpDownload.finishedThread++;
                synchronized (MutilHttpDownload.path) {
                    if(MutilHttpDownload.finishedThread == MutilHttpDownload.PROCESSNUM) {
                        for(int i = 0; i < MutilHttpDownload.PROCESSNUM; i++) {
                            File f = new File("temp" + i + ".txt");
                            System.out.println("删除" + f.getName() +"文件");
                            f.delete();
                        }
                        //只让一个线程进来删除文件,要不然会出异常
                        MutilHttpDownload.finishedThread = 0;
                    }
                }
            }
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }        
        
    }
}


多线程断点续传的DEMO

标签:

原文地址:http://my.oschina.net/Sheamus/blog/493418

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!