源码链接
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.MalformedURLException;
9 import java.net.URL;
10 import java.net.URLConnection;
11
12
13 public class MutileThreadDownload {
14 /**
15 * 线程的数量
16 */
17 private static int threadCount = 3;
18 /**
19 * 每个下载区块的大小
20 */
21 private static long blocksize;
22 /**
23 * 正在运行的线程的数量
24 */
25 private static int runningThreadCount;
26 /**
27 *
28 * @param args
29 * @throws Exception
30 */
31 public static void main(String[] args) throws Exception {
32 //服务器路径
33 String path = "http://download.java.net/jdk/jdk-api-localizations/jdk-api-zh-cn/publish/1.6.0/chm/JDK_API_1_6_zh_CN.CHM";
34 URL url = new URL(path);
35 HttpURLConnection conn = (HttpURLConnection) url.openConnection();
36 conn.setRequestMethod("GET");
37 conn.setReadTimeout(5000);
38 int code = conn.getResponseCode();
39 if(code == 200) {
40 long size = conn.getContentLength();//得到服务器端返回的文件的大小
41 System.out.println("服务器文件的大小:" + size);
42 blocksize = size / threadCount;
43 //1.首先在本地创建一个大小跟服务器一模一样的空白文件
44 File file = new File("temp.CHM");
45 RandomAccessFile raf = new RandomAccessFile(file, "rw");
46 raf.setLength(size);
47 //2.开启若干个子线程分别去下载对应的资源
48 runningThreadCount = threadCount;
49 for(int i = 1;i <= threadCount; i++) {
50 long startIndex = (i - 1) * blocksize;
51 long endIndex = i * blocksize - 1;
52 if(i == threadCount) {
53 //最后一个线程
54 endIndex = size - 1;
55 }
56 System.out.println("开启线程:" + i + "下载的位置:" + startIndex + "~" + endIndex);
57 new DownloadThread(i, startIndex, endIndex, path).start();
58 }
59 }
60 conn.disconnect();
61 }
62
63 private static class DownloadThread extends Thread {
64 private int threadId;
65 private long startIndex;
66 private long endIndex;
67 private String path;
68
69 public DownloadThread(int threadId, long startIndex, long endIndex,
70 String path) {
71 super();
72 this.threadId = threadId;
73 this.startIndex = startIndex;
74 this.endIndex = endIndex;
75 this.path = path;
76 }
77
78 public void run() {
79 try {
80 //当前线程下载的总大小
81 int total = 0;
82 File positionFile = new File(threadId + ".txt");
83 URL url = new URL(path);
84 HttpURLConnection conn = (HttpURLConnection) url.openConnection();
85 conn.setRequestMethod("GET");
86 //接着从上一次的位置继续下载数据
87 if(positionFile.exists() && positionFile.length() > 0) { //判断是否有记录
88 FileInputStream fis = new FileInputStream(positionFile);
89 BufferedReader br = new BufferedReader(new InputStreamReader(fis));
90 //获取当前线程上次下载的总大小是多少
91 String lasttotalstr = br.readLine();
92 int lastTotal = Integer.valueOf(lasttotalstr);
93 System.out.println("上次线程" + threadId + "下载的总大小:" + lastTotal);
94 startIndex += lastTotal; //加上上次下载的总大小
95 fis.close();
96 }
97
98 conn.setRequestProperty("Range", "bytes=" + startIndex + "-" +endIndex);
99 conn.setConnectTimeout(5000);
100 int code = conn.getResponseCode();
101 System.out.println("code=" + code);
102 InputStream is = conn.getInputStream();
103 File file = new File("temp.CHM");
104 RandomAccessFile raf = new RandomAccessFile(file, "rw");
105 raf.seek(startIndex);
106 System.out.println("第" + threadId + "个线程:写文件的开始位置:" + String.valueOf(startIndex));
107
108 int len = 0;
109 byte[] buffer = new byte[1024 * 1024];
110 while((len = is.read(buffer)) != -1) {
111 RandomAccessFile rf = new RandomAccessFile(positionFile, "rwd");//"rwd" 打开以便读取和写入,对于 "rw",还要求对文件内容的每个更新都同步写入到底层存储设备。
112 raf.write(buffer, 0, len);
113 total += len;
114 rf.write(String.valueOf(total).getBytes());
115 rf.close();
116 }
117 is.close();
118 raf.close();
119 //conn.disconnect();
120
121 } catch (Exception e) {
122 e.printStackTrace();
123 }finally {
124 //只有所有线程都下载完毕后,才可以删除记录文件
125 synchronized (MutileThreadDownload.class) { //线程安全
126 System.out.println("线程" + threadId + "下载完毕了");
127 runningThreadCount--;
128 if(runningThreadCount < 1) {
129 System.out.println("所有线程都工作完毕了。删除临时记录的文件");
130 for (int i = 1; i <= threadCount; i++) {
131 File f = new File(i + ".txt");
132 System.out.println(f.delete());
133 }
134 }
135 }
136 }
137 }
138 }
139 }
140