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
#学习笔记,如有谬误,敬请指正。#