JAVA多线程下载网络文件
JAVA多线程下载网络文件,开启多个线程,同时下载网络文件。
源码如下:(点击下载 MultiThreadDownload.java)
1 import java.io.InputStream; 2 import java.io.RandomAccessFile; 3 import java.net.HttpURLConnection; 4 import java.net.URL; 5 6 /** 7 * 说明: 8 * 每一个线程下载的位置计算方式: 9 * 开始位置: (线程id - 1) * 每一块大小 10 * 结束位置: (线程id*每一块大小) - 1 11 * 12 * 注意:有时候不一定能够整除,所以最后一个线程的结束位置应该是文件的末尾 13 * 14 * 步骤: 15 * 1.本地创建一个大小跟服务器文件相同的临时文件 16 * 2.计算分配几个线程去下载服务器上的资源,知道每个线程下载文件的位置 17 * 3.开启三个线程,每一个线程下载对应位置的文件 18 * 4.如果所有的线程,都把自己的数据下载完毕后,服务器上的资源都被下载到本地了 19 * 20 * 作者: zhoubang 21 * 日期:2015年8月7日 上午11:20:06 22 */ 23 public class MultiThreadDownload { 24 public static String path = "http://static.csdn.net/public/common/toolbar/css/index.css"; // 要下载的网络资源文件路径 25 public static int threadCount = 10; // 开启的线程数 26 public static int runningThread = 10; // 记录已经运行的线程数量 27 public static long startTime; 28 29 private static final String filePath = "f:\\index.css"; //文件存放本地的路径 30 31 /** 32 * 测试下载 33 * 34 * 作者: zhoubang 35 * 日期:2015年8月7日 上午11:16:23 36 * @param args 37 * @throws Exception 38 */ 39 public static void main(String[] args) throws Exception { 40 startTime = System.currentTimeMillis(); 41 // 1.连接服务器,获取一个文件,获取文件的长度,在本地创建一个跟服务器一样大小的临时文件 42 URL url = new URL(path); 43 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 44 conn.setConnectTimeout(5000); 45 conn.setRequestMethod("GET"); 46 int code = conn.getResponseCode(); 47 if (code == 200) { 48 // 服务器端返回的数据的长度,实际上就是文件的长度 49 int length = conn.getContentLength(); 50 System.out.println("文件总长度:" + length); 51 // 在客户端本地创建出来一个大小跟服务器端一样大小的临时文件 52 RandomAccessFile raf = new RandomAccessFile(filePath, "rwd"); 53 // 指定创建的这个文件的长度 54 raf.setLength(length); 55 raf.close(); 56 // 假设是3个线程去下载资源。 57 // 平均每一个线程下载的文件大小. 58 int blockSize = length / threadCount; 59 for (int threadId = 1; threadId <= threadCount; threadId++) { 60 // 第一个线程下载的开始位置 61 int startIndex = (threadId - 1) * blockSize; 62 int endIndex = threadId * blockSize - 1; 63 if (threadId == threadCount) {// 最后一个线程下载的长度要稍微长一点 64 endIndex = length; 65 } 66 System.out.println("线程:" + threadId + "下载:---" + startIndex + "--->" + endIndex); 67 new DownLoadThread(path, threadId, startIndex, endIndex).start(); 68 } 69 } else { 70 System.out.printf("服务器错误!"); 71 } 72 } 73 74 /** 75 * 下载文件的子线程,每一个线程下载对应位置的文件 76 * 77 * 作者: zhoubang 78 * 日期:2015年8月7日 上午11:16:34 79 */ 80 public static class DownLoadThread extends Thread { 81 private int threadId; 82 private int startIndex; 83 private int endIndex; 84 85 /** 86 * @param path 87 * 下载文件在服务器上的路径 88 * @param threadId 89 * 线程Id 90 * @param startIndex 91 * 线程下载的开始位置 92 * @param endIndex 93 * 线程下载的结束位置 94 */ 95 public DownLoadThread(String path, int threadId, int startIndex, int endIndex) { 96 super(); 97 this.threadId = threadId; 98 this.startIndex = startIndex; 99 this.endIndex = endIndex; 100 } 101 102 @Override 103 public void run() { 104 try { 105 URL url = new URL(path); 106 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 107 conn.setConnectTimeout(5000); 108 conn.setRequestMethod("GET"); 109 // 重要:请求服务器下载部分文件 指定文件的位置 110 conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); 111 // 从服务器请求全部资源返回200 ok如果从服务器请求部分资源 返回 206 ok 112 int code = conn.getResponseCode(); 113 System.out.println("code:" + code); 114 InputStream is = conn.getInputStream();// 已经设置了请求的位置,返回的是当前位置对应的文件的输入流 115 RandomAccessFile raf = new RandomAccessFile(filePath, "rwd"); 116 // 随机写文件的时候从哪个位置开始写 117 raf.seek(startIndex);// 定位文件 118 119 int len = 0; 120 byte[] buffer = new byte[1024]; 121 while ((len = is.read(buffer)) != -1) { 122 raf.write(buffer, 0, len); 123 } 124 is.close(); 125 raf.close(); 126 System.out.println("线程:" + threadId + "下载完毕"); 127 System.out.println((System.currentTimeMillis() - startTime)); 128 } catch (Exception e) { 129 e.printStackTrace(); 130 } finally { 131 runningThread--; 132 if (runningThread == 0) {// 所有的线程执行完毕 133 System.out.println("文件全部下载完毕!"); 134 } 135 } 136 } 137 138 } 139 }
欢迎访问 JAVA技术分享 www.2b2b92b.com