源码链接

  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  

 

 posted on 2014-12-02 23:46  zhangbz  阅读(308)  评论(0编辑  收藏  举报