Java多线程文件下载
来源:互联网 发布:什么是大数据云计算 编辑:程序博客网 时间:2024/05/16 06:01
一. 多线程下载文件考虑处理步骤:
1. 如何获取文件的长度
2. 合理的创建线程数量,并计算每一个线程下载的长度
3. 如何将多个线程下载的字节写入到文件中
二. 代码实现如下:
package com.bochao.download;import java.io.File;import java.net.URL;import java.net.URLConnection;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** * HTTP多线程下载 * * @Author DuanCZ * @Date 2015年9月30日-上午9:28:28 */public class HttpMulitThreadDownload {// 下载文件路径private String downloadFilePath = null;// 保存文件路径private String saveFileDir = "c:\\";// 默认合理并发线程数private int threadCount = Runtime.getRuntime().availableProcessors() * 2;// 新文件名称private String newFileName = null;public HttpMulitThreadDownload(int threadCount, String downloadFilePath, String saveFileDir, String newFileName) {// 用户指定线程数如果小于默认线程数则使用用户指定线程数if (threadCount < this.threadCount) {this.threadCount = threadCount;}this.downloadFilePath = downloadFilePath;this.saveFileDir = saveFileDir;this.newFileName = newFileName;}public void MulitThreadDownload() {// 数据合法性验证if (null == downloadFilePath || downloadFilePath.isEmpty()) {throw new RuntimeException("请指定下载路径!");}if (null == saveFileDir || saveFileDir.isEmpty()) {throw new RuntimeException("请指定保存路径!");}// 创建保存文件路径如果不存在File saveFileDirTemp = new File(saveFileDir);if (!saveFileDirTemp.exists()) {saveFileDirTemp.mkdirs();}// 处理文件名称if (null == newFileName || newFileName.isEmpty()) {newFileName = downloadFilePath.substring(downloadFilePath.lastIndexOf("/") + 1, downloadFilePath.length());}// 创建固定大小的线程池ExecutorService threadPool = Executors.newFixedThreadPool(threadCount);try {// 根据文件长度计算合理线程数开始URLConnection urlConnection = new URL(downloadFilePath).openConnection();// 获取文件长度int downloadFileLength = urlConnection.getContentLength();// 计算每个线程负责的文件字节长度int averageThreadLength = downloadFileLength / threadCount;int residueThreadLength = downloadFileLength % threadCount;// 让每一个线程开始工作int startIndex = 0;int endIndex = 0;for (int i = 0; i < threadCount; i++) {// 计算每一个线程开始和计数索引startIndex = i * averageThreadLength;// 如果是最后一个线程,则将剩余的全部下载if ((i + 1) == threadCount) {endIndex = (i + 1) * averageThreadLength + residueThreadLength - 1;}endIndex = (i + 1) * averageThreadLength - 1;// 创建下载线程对象DownloadHandlerThread downloadHandlerThread = new DownloadHandlerThread();downloadHandlerThread.setDownloadFilePath(downloadFilePath);downloadHandlerThread.setSaveFilePath(saveFileDir + newFileName);downloadHandlerThread.setStartIndex(startIndex);downloadHandlerThread.setEndIndex(endIndex);threadPool.execute(downloadHandlerThread);}} catch (Exception e) {e.printStackTrace();} finally {// 关闭线程池threadPool.shutdown();}}}
package com.bochao.download;import java.io.IOException;import java.io.InputStream;import java.io.RandomAccessFile;import java.net.URL;import java.net.URLConnection;import java.text.SimpleDateFormat;import java.util.Date;/** * 下载文件处理线程 * * @Author DuanCZ * @Date 2015年9月30日-上午11:38:42 */public class DownloadHandlerThread implements Runnable { // 待下载的HTTP文件路径 private String downloadFilePath = null; // 下载保存文件路径 private String saveFilePath = null; // 文件随机写入开始索引 private int startIndex = 0; // 文件随机写入结束索引 private int endIndex = 0; @Override public void run() { System.out.println("线程名称[" + Thread.currentThread().getName() + "]于时间[" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "]开始下载...."); // 文件输入流对象 InputStream fileInputStream = null; // 随机访问文件 RandomAccessFile randomAccessFile = null; // ------------------------------------------------------------------------------ // 获取随机文件流开始 // 获取一个URL打开链接对象 URLConnection urlConnection = null; try { urlConnection = new URL(downloadFilePath).openConnection(); } catch (IOException e1) { e1.printStackTrace(); } // 设置该链接允许和用户交互 urlConnection.setAllowUserInteraction(true); // 设置请求属性字节范围 urlConnection.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex + ""); try { // 获取指定的文件流 fileInputStream = urlConnection.getInputStream(); } catch (IOException e) { e.printStackTrace(); } // ------------------------------------------------------------------------------获取随机文件流结束 // ------------------------------------------------------------------------ // 写文件流到指定的文件开始 try { // 创建文件随机访问对象 randomAccessFile = new RandomAccessFile(saveFilePath, "rw"); // 将文件写入位置移动到其实点 randomAccessFile.seek(startIndex); // 写入文件 int bytes = 0; byte[] buffer = new byte[100 * 1024]; while ((bytes = fileInputStream.read(buffer, 0, buffer.length)) != -1) { randomAccessFile.write(buffer, 0, bytes); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (null != randomAccessFile) { randomAccessFile.close(); } if (null != fileInputStream) { fileInputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } // ------------------------------------------------------------------------写文件流到指定的文件结束 System.out.println("线程名称[" + Thread.currentThread().getName() + "]于时间[" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "]下载完成!"); } public String getDownloadFilePath() { return downloadFilePath; } public void setDownloadFilePath(String downloadFilePath) { this.downloadFilePath = downloadFilePath; } public String getSaveFilePath() { return saveFilePath; } public void setSaveFilePath(String saveFilePath) { this.saveFilePath = saveFilePath; } public int getStartIndex() { return startIndex; } public void setStartIndex(int startIndex) { this.startIndex = startIndex; } public int getEndIndex() { return endIndex; } public void setEndIndex(int endIndex) { this.endIndex = endIndex; }}
测试:
package com.bochao.download;public class TestDownload {public static void main(String[] args) { String downloadFilePath = "http://localhost:81/mulitThreadDownload/file/PowerDesigner165_Evaluation.1428562995.exe";String saveFileDir= "f:\\Download\\";HttpMulitThreadDownload httpMulitThreadDownload = new HttpMulitThreadDownload(2, downloadFilePath, saveFileDir, "powerdesigner.exe");httpMulitThreadDownload.MulitThreadDownload();}}
输出结果:
线程名称[pool-1-thread-1]于时间[2015-08-30 16:09:49]开始下载....
线程名称[pool-1-thread-2]于时间[2015-08-30 16:09:49]开始下载....
线程名称[pool-1-thread-2]于时间[2015-09-30 16:09:01]下载完成!
线程名称[pool-1-thread-1]于时间[2015-09-30 16:09:23]下载完成!
0 0
- Java多线程下载文件
- java多线程下载文件
- Java多线程下载文件
- Java多线程下载文件
- Java多线程下载文件
- Java多线程下载文件
- Java 文件多线程下载
- java 多线程下载文件
- Java多线程下载文件
- java多线程下载文件
- Java多线程文件下载
- java多线程下载文件
- JAVA 多线程下载文件
- Java多线程下载文件
- Java 多线程断点下载文件
- Java 多线程断点下载文件
- Java 多线程断点下载文件
- Java 多线程断点下载文件
- HDU 5194 DZY Loves Balls
- 1013. Battle Over Cities (25) 连通子集 连通分量的数量
- Android 布局优化
- 为什么这段代码输出的是”Hello World”
- ABAP 报表求和统计功能实现方法
- Java多线程文件下载
- JavaMelody Maven 配置 及简单应用
- JSON 在java javascript中的应用
- doT.js初窥二
- Eclipse集成python
- 学习记录
- 第四周--项目五--猴子选大王
- java系统学习(十四) --------数据结构
- 学习ThinkPHP3.2.2(一):记录一下第一个例子的运行过程