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 }
浙公网安备 33010602011771号