我们现在创建一个简单的多线程解析资源
public class DownLoadRunable implements Runnable { private int threadId; private int startIndex; private int endIndex; private String path; public DownLoadRunable(String path,int threadId, int startIndex, int endIndex) { super(); this.threadId = threadId; this.startIndex = startIndex; this.endIndex = endIndex; this.path = path; } /* * (non-Javadoc) * * @see java.lang.Runnable#run() */ @Override public void run() { URL url; try { url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5000); conn.setRequestMethod("GET"); // 重要:请求服务器下载部分文件 指定文件的位置 conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); // 从服务器请求全部资源返回200 ok如果从服务器请求部分资源 返回 206 ok int code = conn.getResponseCode(); System.out.println("code:" + code); InputStream is = conn.getInputStream();// 已经设置了请求的位置,返回的是当前位置对应的文件的输入流 RandomAccessFile raf = new RandomAccessFile("meinv.jpg", "rwd"); // 随机写文件的时候从哪个位置开始写 raf.seek(startIndex);// 定位文件 int len = 0; byte[] buffer = new byte[1024]; while ((len = is.read(buffer)) != -1) { raf.write(buffer, 0, len); } is.close(); raf.close(); System.out.println("线程:" + threadId + "下载完毕"); } catch (IOException e) { e.printStackTrace(); } } }
/** * @author Janle * */ public class DowloadDemo { // 文件路径 public static String[] paths = { "http://img.ugirls.com/uploads/cooperate/baidu/20160408jzx3.jpg", "http://b.hiphotos.baidu.com/image/h%3D360/sign=a813da3172094b36c4921deb93ce7c00/810a19d8bc3eb135aa449355a21ea8d3fc1f4458.jpg", "http://a.hiphotos.baidu.com/image/h%3D360/sign=c429bad21dd8bc3ed90800ccb28aa6c8/e7cd7b899e510fb3a78c787fdd33c895d0430c44.jpg" }; // 线程数 public static int threadCount = 3; private static ExecutorService threads = Executors.newFixedThreadPool(4); public static void main(String[] args) { try { for (String path : paths) { // 1.连接服务器,获取一个文件,获取文件的长度,在本地创建一个跟服务器一样大小的临时文件 URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5000); conn.setRequestMethod("GET"); int code = conn.getResponseCode();// 获得相应的状态码如果是200就说明请求成功 if (code == 200) { splitTaskToThread(path, conn.getContentLength()); } } threads.shutdown(); } catch (IOException e) { e.printStackTrace(); } } /** * 将资源拆分到线程资源中 * * @param fileSize */ private static void splitTaskToThread(String path, int fileSize) { // 假设是3个线程去下载资源。 // 平均每一个线程下载的文件大小. int blockSize = fileSize / threadCount;// 线程执行块的大小 for (int threadId = 1; threadId <= threadCount; threadId++) { // 线程下载的开始位置 int startIndex = (threadId - 1) * blockSize;// 线程执行开始位置 int endIndex = threadId * blockSize - 1; if (threadId == threadCount) {// 如果任务分配线程和线程的数量相同的时候直接将最后位置给截止位置【最后一块稍微大点】 endIndex = fileSize; } threads.execute(new DownLoadRunable(path, startIndex, endIndex)); } } } class DownLoadRunable implements Runnable { private int startIndex; private int endIndex; private String path; public DownLoadRunable(String path, int startIndex, int endIndex) { super(); this.startIndex = startIndex; this.endIndex = endIndex; this.path = path; } /* * (non-Javadoc) * * @see java.lang.Runnable#run() */ @Override public void run() { URL url; try { url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5000); conn.setRequestMethod("GET"); // 重要:请求服务器下载部分文件 指定文件的位置 conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); // 从服务器请求全部资源返回200 ok如果从服务器请求部分资源 返回 206 ok int code = conn.getResponseCode(); System.out.println("code:" + code); InputStream is = conn.getInputStream();// 已经设置了请求的位置,返回的是当前位置对应的文件的输入流 String urlPath = conn.getURL().getFile(); String fileFullName = urlPath.substring(urlPath.lastIndexOf("/") + 1); RandomAccessFile raf = new RandomAccessFile(fileFullName, "rwd"); // 随机写文件的时候从哪个位置开始写 raf.seek(startIndex);// 定位文件 int len = 0; byte[] buffer = new byte[1024]; while ((len = is.read(buffer)) != -1) { raf.write(buffer, 0, len); } is.close(); raf.close(); System.out.println("线程:" + Thread.currentThread().getName() + "下载完毕"); } catch (IOException e) { e.printStackTrace(); } } }
多线程分发
(size / nThreads * i, size / nThreads * (i + 1));