代码没有优化,暂时先实现结果
package download; import java.io.File; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; /** * @author Liu Yutao * @className Down * @email koal@vip.qq.com * @date 2016/4/7 21:11 */ public class Down { //下载地址 public static final String DOWNFILE = "http://219.150.176.188/files/WindowsXP_SP2.exe"; //线程数 public static final int THREADCOUNT = 5; //格式化文件,得到文件名称 public static String formatFileName(String value) { //得到最后一个/位置 int indexOf = value.lastIndexOf("/"); //截取/WindowsXP_SP2.exe文件名 String fileName = value.substring(indexOf + 1, value.length()); return fileName; } //下载文件 public static void httpDownload(String downfile) { try { URL url = new URL(DOWNFILE); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); //超时5秒 connection.setReadTimeout(5000); connection.setRequestMethod("GET"); int code = connection.getResponseCode(); if (code == 200) { //得到文件长度 long length = connection.getContentLength(); InputStream stream = connection.getInputStream(); File file = new File(formatFileName(DOWNFILE)); //用于创建一个和目标文件大小一样的空文件,为了就是占坑(rw是可读可写模式read,write) RandomAccessFile accessFile = new RandomAccessFile(file, "rw"); accessFile.setLength(length); //分10个线程,每个线程的区块长度(总长度 ÷ 个数) long blockSize = length / THREADCOUNT; for (int threadId = 0; threadId < THREADCOUNT; threadId++) { //开始区块 // 当前循环线程编号 x 当前线程区块长度(0x1024,1x1024,2x1024) long beginIndex = threadId * blockSize; //结束区块 // 当前线程+1 x 每个区块大小 = 下次循环的开始区块,再 -1 就等于本次区块的最后位置 long endIndex = (threadId + 1) * blockSize - 1; //是否最后一个线程 if (threadId == (THREADCOUNT - 1)) { endIndex = length - 1; } System.err.println("当前线程:" + (threadId+1) + ",开始区块:" + beginIndex + ",结束区块:" + endIndex); new ThreadDownloadRun(threadId, beginIndex, endIndex).start(); } } } catch (Exception e) { e.printStackTrace(); } } public static class ThreadDownloadRun extends Thread { private long threadId; private long beginIndex; private long endIndex; //构造 public ThreadDownloadRun(long threadId, long beginIndex, long endIndex) { this.threadId = threadId; this.beginIndex = beginIndex; this.endIndex = endIndex; } @Override public void run() { try { System.err.println("当前线程:" + (threadId+1) + ",开始下载......"); URL url = new URL(DOWNFILE); HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setRequestMethod("GET"); //设置http文件头的range(区间) urlConnection.setRequestProperty("Range", "bytes=" + beginIndex + "-" + endIndex); int code = urlConnection.getResponseCode(); //区间返回是206 if (code == 206) { //得到数据 InputStream stream = urlConnection.getInputStream(); File file = new File(formatFileName(DOWNFILE)); RandomAccessFile accessFile = new RandomAccessFile(file, "rw"); //设置RandomAccessFile写入文件的区块开始长度 accessFile.seek(beginIndex); //下载开始 byte[] bytes = new byte[1024 * 1024]; int len = 0; while ((len = stream.read(bytes)) > 0) { accessFile.write(bytes, 0, len); } accessFile.close(); stream.close(); System.err.println("当前线程:" + (threadId+1) + ",下载结束!!!"); } } catch (Exception e) { e.printStackTrace(); } } } public static void main(String[] args) { httpDownload(DOWNFILE); } }