多线程同步下载

Posted on 2016-03-31 13:38  邱小贱  阅读(207)  评论(0)    收藏  举报
  1 import java.io.BufferedReader;
  2 import java.io.File;
  3 import java.io.FileInputStream;
  4 import java.io.InputStream;
  5 import java.io.InputStreamReader;
  6 import java.io.RandomAccessFile;
  7 import java.net.HttpURLConnection;
  8 import java.net.URL;
  9 
 10 public class MultiThreadDownLoad {
 11     static int ThreadCount = 3;
 12     static int finish = 0;
 13     // 确定下载地址http://10.16.154.24:8080/Nox.exe
 14     static String path = "http://10.16.154.24:8080/Nox.exe";
 15 
 16     public static void main(String[] args) {
 17 
 18         String filename = path.substring(path.lastIndexOf("/") + 1);
 19         // 发送GET请求,请求这个地址的资源
 20         try {
 21             URL url = new URL(path);
 22             HttpURLConnection conn = (HttpURLConnection) url.openConnection();
 23             conn.setReadTimeout(3000);
 24             conn.setConnectTimeout(3000);
 25             conn.setRequestMethod("GET");
 26 
 27             if (conn.getResponseCode() == 200) {
 28                 // 拿到所有请求资源文件的长度
 29                 int length = conn.getContentLength();
 30 
 31                 File file = new File(filename);
 32                 // 随机存储文件对象,生成临时文件
 33                 RandomAccessFile raf = new RandomAccessFile(file, "rwd");
 34                 // 设置临时文件的大小
 35                 raf.setLength(length);
 36                 raf.close();
 37                 // 计算每个线程应该下载多少字节
 38                 int size = length / ThreadCount;
 39 
 40                 for (int i = 0; i < ThreadCount; i++) {
 41                     // 计算线程下载的开始和结束位置
 42                     int startIndex = i * size;
 43                     int endIndex = (i + 1) * size - 1;
 44                     // 如果是最后一个线程,那么结束位置写死
 45                     if (i == ThreadCount - 1) {
 46                         endIndex = length - 1;
 47                     }
 48                     new DownLoadThread(startIndex, endIndex, i).start();
 49                 }
 50 
 51             }
 52 
 53         } catch (Exception e) {
 54             e.printStackTrace();
 55         }
 56     }
 57 }
 58 
 59 class DownLoadThread extends Thread {
 60     int startIndex;
 61     int endIndex;
 62     int threadId;
 63 
 64     public DownLoadThread(int startIndex, int endIndex, int threadId) {
 65         super();
 66         this.startIndex = startIndex;
 67         this.endIndex = endIndex;
 68         this.threadId = threadId;
 69     }
 70 
 71     public void run() {
 72         String filename = MultiThreadDownLoad.path
 73                 .substring(MultiThreadDownLoad.path.lastIndexOf("/") + 1);
 74         // 生成一个专门用来记录下载进度的临时文件
 75         File progressFile = new File(threadId + ".txt");
 76 
 77         // 再次发送http请求,下载源文件
 78         try {
 79             // 判断进度临时未见是否存在
 80             if (progressFile.exists()) {
 81                 FileInputStream fis = new FileInputStream(progressFile);
 82                 BufferedReader br = new BufferedReader(new InputStreamReader(
 83                         fis));
 84                 // 从进度临时文件中读取上一次下载的总进度,然后与原本的开始位置相加,得到新的开始位置
 85                 startIndex += Integer.parseInt(br.readLine());
 86                 fis.close();
 87             }
 88             URL url = new URL(MultiThreadDownLoad.path);
 89             HttpURLConnection conn = (HttpURLConnection) url.openConnection();
 90             conn.setReadTimeout(3000);
 91             conn.setConnectTimeout(3000);
 92             conn.setRequestMethod("GET");
 93             // 设置本次http请求的数据的区间
 94             conn.setRequestProperty("Range", "byte=" + startIndex + "-"
 95                     + endIndex);
 96 
 97             // 请求部分数据,相应码是206
 98             if (conn.getResponseCode() == 206) {
 99                 // 流里此时只有1/3源文件的数据
100                 InputStream is = conn.getInputStream();
101                 byte[] buffer = new byte[1024];
102                 int len = 0, total = 0;
103                 File file = new File(filename);
104                 // 随机存储文件对象,生成临时文件
105                 RandomAccessFile raf = new RandomAccessFile(file, "rwd");
106                 // 把文件的写入位置移动到startIndex
107                 raf.seek(startIndex);
108                 while ((len = is.read(buffer)) != -1) {
109                     // 每次读取流里数据之后,同步把数据写入临时文件
110                     raf.write(buffer, 0, len);
111                     total += len;
112                     System.out.println("线程" + threadId + "下载了" + total);
113 
114                     RandomAccessFile progressRaf = new RandomAccessFile(
115                             progressFile, "rwd");
116                     // 每次读取流里数据之后,同步把当前线程下载的总进度写入进度临时文件中
117                     progressRaf.write((total + "").getBytes());
118                     progressRaf.close();
119 
120                 }
121                 raf.close();
122                 MultiThreadDownLoad.finish++;
123                 synchronized (MultiThreadDownLoad.path) {
124                     if (MultiThreadDownLoad.finish == MultiThreadDownLoad.ThreadCount) {
125                         for (int i = 0; i < MultiThreadDownLoad.ThreadCount; i++) {
126                             File f = new File(i + ".txt");
127                             f.delete();
128                         }
129                     }
130                     MultiThreadDownLoad.finish = 0;
131                 }
132 
133             }
134         } catch (Exception e) {
135             e.printStackTrace();
136         }
137 
138     }
139 }

 

博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3