package cn.mark.work0312; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; /** * 多线程下载 */ public class MutiDownload { /*线程数*/ private static final int THREAD_COUNT = 5; /*下载资源*/ private static final String DOWNLOAD_URL = "http://cn.bing.com/az/hprichbg/rb/PlungeDiving_ZH-CN11143756334_1920x1080.jpg"; /*下载位置*/ private static final String FILE_NAME = "D:/down.jpg"; public static void main(String[] args) { //文件大小 long fileSize; HttpURLConnection connection = null; try{ //打开一个链接 connection = (HttpURLConnection) new URL(DOWNLOAD_URL).openConnection(); //设置请求方式 connection.setRequestMethod("GET"); //连接超时 connection.setConnectTimeout(8000); //读取超时 connection.setReadTimeout(8000); if ( connection.getResponseCode() == 200 ){//请求成功返回200 //文件大小 fileSize = connection.getContentLength(); //每个线程要读取的块 long eachSize = fileSize / THREAD_COUNT; //打开一个RandomAccessFile文件,打开方式为读写(rw) RandomAccessFile raf = new RandomAccessFile(FILE_NAME,"rw"); //setLength是先在存储设备占用一块空间,防止下载到一半空间不足 raf.setLength(fileSize); raf.close(); /*创建线程开始下载*/ for ( int i =0; i <THREAD_COUNT; i++ ){ long startIndex = i * eachSize; long endIndex = (i+1) * eachSize -1; if ( i == THREAD_COUNT -1 ){ //最后一个线程直接下到文件末尾 endIndex = fileSize; } new DownloadThread(DOWNLOAD_URL, FILE_NAME, i, startIndex, endIndex).start(); } } }catch(Exception e){ e.printStackTrace(); }finally{ if ( connection != null ){ connection.disconnect(); connection = null; } } } } class DownloadThread extends Thread{ //下载地址 private String url; //文件名 private String fileName; //线程名 private int threadID; //开始块 private long startIndex; //结束块 private long endIndex; //连接 private HttpURLConnection connection; private RandomAccessFile raf; private InputStream inputStream; /** * 构造方法 * @param url 下载路径 * @param fileName 下载文件名 * @param threadID 线程ID * @param startIndex 开始块 * @param endIndex 结束块 */ public DownloadThread(String url, String fileName, int threadID, long startIndex, long endIndex) { this.url = url; this.fileName = fileName; this.threadID = threadID; this.startIndex = startIndex; this.endIndex = endIndex; } @Override public void run() { try { connection = (HttpURLConnection)new URL(url+"?ts="+System.currentTimeMillis()).openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(8000); connection.setReadTimeout(8000); //设置请求范围 connection.setRequestProperty("RANGE", "bytes="+startIndex+"-"+endIndex); //请求部分数据成功,返回200 int code = connection.getResponseCode(); if (code == 200 || code == 206){ inputStream = connection.getInputStream(); byte[] bs = new byte[1024]; int len; raf = new RandomAccessFile(fileName, "rwd"); //把开始位置设置为startIndex,与请求数据一致 raf.seek(startIndex); long total = 0; while ( (len = inputStream.read(bs)) != -1 ){ total += len; System.out.println("线程"+threadID+":"+total); raf.write(bs,0,len); } } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ if ( connection != null ){ connection.disconnect(); connection = null; } if ( raf != null ){ try { raf.close(); } catch (IOException e) { e.printStackTrace(); } } if ( inputStream != null ){ try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } }