当前位置: 首页 > news >正文

(1-6-5)Java 多线程(定长线程池)下载器(案例)

目录

0.案例需求

1. 封装URLConnection 网络下载工具类

2. 读取 config.properties 配置文件

3. 从指定文件读取下载地址,批量下载网络资源

4. 实现多线程(定长线程池)下载 及 本地文件保存

5. 完整版源码


0.案例需求

  1. 通过读取源文件,多线程自动下载所有网络资源到  本地硬盘
  2. 遇到下载故障时,在控制台打印错误信息
  3. 允许自定义源文件地址,保存下载文件的目录要自动创建
  4. 允许自定义同时下载的任务数量,不指定时,默认开启3个下载任务
  5. 下载成功后,在控制太输出存储路径与文件尺寸

代码实现思路

实现效果:

 


1. 封装URLConnection 网络下载工具类

/*** 下载单个文件  保存到本地* @param url   原图片网址* @param targetDir   保存的目标目录*/
// 1. 封装URLConnection 网络下载工具类
public class Downloader {/*** 下载单个文件  保存到本地* @param url   原图片网址* @param targetDir   保存的目标目录*/public int download(String url, String targetDir, int index) {InputStream is = null;OutputStream os = null;try{/*** 由于网络图片不以  文件名结尾* 故采用 id+1 重新命名*/
//            String fileName = url.substring(url.lastIndexOf("/") + 1);String fileName = "摩托姐" + index + ".png";File targetFile = new File(targetDir + "/" +fileName);if(!targetFile.exists()){targetFile.createNewFile();}URL urlObj = new URL(url);URLConnection connection = urlObj.openConnection();is = connection.getInputStream();os = new FileOutputStream(targetFile);byte[] buffer = new byte[1024];int len = 0;while((len = is.read(buffer)) != -1){os.write(buffer, 0, len);}System.out.println("[info]图片下载完毕:" + url + "\n\t  ->" + targetFile.getPath() + "(" + Math.floor(targetFile.length() / 1024) + "kb)");}catch(IOException e){e.printStackTrace();}finally{try{if(os != null){os.close();}if(is != null){is.close();}}catch(IOException e){e.printStackTrace();}}return index++;}public static void main(String[] args) {int index = 1;Downloader downloader = new Downloader();index = downloader.download("https://img2.baidu.com/it/u=1567841056,1924556786&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=667", "D:/game/游戏/王者荣耀/摩托姐", index);}/*** [info]图片下载完毕:https://img2.baidu.com/it/u=1567841056,1924556786&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=667* 	  ->D:\game\游戏\王者荣耀\摩托姐\摩托姐1.png(45.0kb)*/
}

2. 读取 config.properties 配置文件

config.properties

thread-num = 3
#中文路径访问不到
#target-dir = D:/game/游戏/王者荣耀/摩托姐
target-dir = D:/game/wzry/mtj

获取config.properties资源中的属性信息

    public String start(String propDir){System.out.println("propDir:" + propDir);File propFile = new File(propDir + "/config.properties");Properties prop = new Properties();Reader reader = null;String targetDir = "";try{reader = new FileReader(propFile);prop.load(reader);String threadNum = prop.getProperty("thread-num");targetDir = prop.getProperty("target-dir");System.out.println(threadNum);System.out.println(targetDir);}catch (IOException e){e.printStackTrace();}finally{if(reader != null){try {reader.close();} catch (IOException e) {e.printStackTrace();}}}return targetDir;}public static void main(String[] args) {int index = 2;Downloader2 downloader2 = new Downloader2();String path = downloader2.start("D:/s_java/se/6-5moreThreadDownloader/downloader/src");index = downloader2.download("https://img2.baidu.com/it/u=1567841056,1924556786&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=667", path, index);}

3. 从指定文件读取下载地址,批量下载网络资源

download.txt
https://img2.baidu.com/it/u=1567841056,1924556786&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=667
https://img0.baidu.com/it/u=4153860329,1779549628&fm=253&app=138&f=JPEG?w=1570&h=800
https://img1.baidu.com/it/u=1390259360,3605622436&fm=253&app=138&f=JPEG?w=1534&h=800
https://img2.baidu.com/it/u=799013572,638024149&fm=253&app=138&f=JPEG?w=1570&h=800
https://img2.baidu.com/it/u=1702949672,1328662943&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1778
https://img0.baidu.com/it/u=2015490030,1225562827&fm=253&app=138&f=JPEG?w=800&h=1778
https://images.pianwan.com/img/h1/h231/img202206241604390_info586X364.png
Downloader3.java
package com.vb.loader;import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;// 3. 读取 download.txt 下载列表
public class Downloader3 {public void download(String url, String targetDir, int index) {InputStream is = null;OutputStream os = null;try{
//            String fileName = url.substring(url.lastIndexOf("/") + 1);String fileName = "摩托姐" + index + ".png";File targetFile = new File(targetDir + "/" +fileName);if(!targetFile.exists()){targetFile.createNewFile();}URL urlObj = new URL(url);URLConnection connection = urlObj.openConnection();is = connection.getInputStream();os = new FileOutputStream(targetFile);byte[] buffer = new byte[1024];int len = 0;while((len = is.read(buffer)) != -1){os.write(buffer, 0, len);}System.out.println("[info]图片下载完毕:" + url + "\n\t  ->" + targetFile.getPath() + "(" + Math.floor(targetFile.length() / 1024) + "kb)");}catch(IOException e){e.printStackTrace();}finally{try{if(os != null){os.close();}if(is != null){is.close();}}catch(IOException e){e.printStackTrace();}}}public void start(String propDir){System.out.println("propDir:" + propDir);File propFile = new File(propDir + "/config.properties");Properties prop = new Properties();Reader reader = null;String targetDir = "";try{reader = new FileReader(propFile);prop.load(reader);String threadNum = prop.getProperty("thread-num");targetDir = prop.getProperty("target-dir");//            System.out.println(threadNum);
//            System.out.println(targetDir);this.multiDownloaderFile(targetDir, propDir + "/download.txt");}catch (IOException e){e.printStackTrace();}finally{if(reader != null){try {reader.close();} catch (IOException e) {e.printStackTrace();}}}}/*** 从指定文件读取下载地址,批量下载网络资源* @param targetDir    下载后文件的存放目录* @param downloadTxtPath   download文件的路径*/public void multiDownloaderFile(String targetDir, String downloadTxtPath){File targetFile = new File(targetDir);if(!targetFile.exists()){targetFile.mkdirs();System.out.println("自动创建目录:" + targetDir);}System.out.println("目标目录:"+ targetDir);List<String> resPaths = new ArrayList<String>();BufferedReader reader = null;try{int flag = 1;reader = new BufferedReader(new FileReader(downloadTxtPath));String line = null;while((line = reader.readLine()) != null){resPaths.add(line);
//                System.out.println(line);this.download(line, targetDir, flag);flag++;}}catch(IOException e){e.printStackTrace();}finally{if(reader != null){try{reader.close();}catch(IOException e){e.printStackTrace();}}}}public static void main(String[] args) {
//        int index = 1;Downloader3 downloader2 = new Downloader3();downloader2.start("D:/s_java/se/6-5moreThreadDownloader/downloader/src");
//        String path = downloader2.start("D:/s_java/se/6-5moreThreadDownloader/downloader/src");
//        index = downloader2.download("https://img2.baidu.com/it/u=1567841056,1924556786&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=667", path, index);}/*** propDir:D:/s_java/se/6-5moreThreadDownloader/downloader/src* 目标目录:D:/game/wzry/mtj* [info]图片下载完毕:https://img2.baidu.com/it/u=1567841056,1924556786&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=667* 	  ->D:\game\wzry\mtj\摩托姐1.png(45.0kb)* [info]图片下载完毕:https://img0.baidu.com/it/u=4153860329,1779549628&fm=253&app=138&f=JPEG?w=1570&h=800* 	  ->D:\game\wzry\mtj\摩托姐2.png(141.0kb)* [info]图片下载完毕:https://img1.baidu.com/it/u=1390259360,3605622436&fm=253&app=138&f=JPEG?w=1534&h=800* 	  ->D:\game\wzry\mtj\摩托姐3.png(105.0kb)* [info]图片下载完毕:https://img2.baidu.com/it/u=799013572,638024149&fm=253&app=138&f=JPEG?w=1570&h=800* 	  ->D:\game\wzry\mtj\摩托姐4.png(133.0kb)* [info]图片下载完毕:https://img2.baidu.com/it/u=1702949672,1328662943&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1778* 	  ->D:\game\wzry\mtj\摩托姐5.png(110.0kb)* [info]图片下载完毕:https://img0.baidu.com/it/u=2015490030,1225562827&fm=253&app=138&f=JPEG?w=800&h=1778* 	  ->D:\game\wzry\mtj\摩托姐6.png(177.0kb)* [info]图片下载完毕:https://images.pianwan.com/img/h1/h231/img202206241604390_info586X364.png* 	  ->D:\game\wzry\mtj\摩托姐7.png(362.0kb)*/
}

4. 实现多线程(定长线程池)下载 及 本地文件保存

// 4. 实现多线程下载 及 本地文件保存
public class Downloader4 {private Integer threadNum = 2;public void download(String url, String targetDir, int index) {InputStream is = null;OutputStream os = null;try{
//            String fileName = url.substring(url.lastIndexOf("/") + 1);String fileName = "摩托姐" + index + ".png";File targetFile = new File(targetDir + "/" +fileName);if(!targetFile.exists()){targetFile.createNewFile();}URL urlObj = new URL(url);URLConnection connection = urlObj.openConnection();is = connection.getInputStream();os = new FileOutputStream(targetFile);byte[] buffer = new byte[1024];int len = 0;while((len = is.read(buffer)) != -1){os.write(buffer, 0, len);}
//            System.out.println("[info]图片下载完毕:" + url + "\n\t  ->" + targetFile.getPath() + "(" + Math.floor(targetFile.length() / 1024) + "kb)");}catch(IOException e){e.printStackTrace();}finally{try{if(os != null){os.close();}if(is != null){is.close();}}catch(IOException e){e.printStackTrace();}}}public void start(String propDir){System.out.println("propDir:" + propDir);File propFile = new File(propDir + "/config.properties");Properties prop = new Properties();Reader reader = null;String targetDir = "";try{reader = new FileReader(propFile);prop.load(reader);String threadNum = prop.getProperty("thread-num");this.threadNum = Integer.parseInt(threadNum);targetDir = prop.getProperty("target-dir");this.multiDownloaderFile(targetDir, propDir + "/download.txt");}catch (IOException e){e.printStackTrace();}finally{if(reader != null){try {reader.close();} catch (IOException e) {e.printStackTrace();}}}}/*** 从指定文件读取下载地址,批量下载网络资源* @param targetDir    下载后文件的存放目录* @param downloadTxtPath   download文件的路径*/public void multiDownloaderFile(String targetDir, String downloadTxtPath){File targetFile = new File(targetDir);if(!targetFile.exists()){targetFile.mkdirs();System.out.println("自动创建目录:" + targetDir);}System.out.println("目标目录:"+ targetDir);List<String> resPaths = new ArrayList<String>();BufferedReader reader = null;ExecutorService threadPool = null;int flag = 1;try{reader = new BufferedReader(new FileReader(downloadTxtPath));String line = null;while((line = reader.readLine()) != null){resPaths.add(line);
//                System.out.println(line);// 单线程处理
//                this.download(line, targetDir, flag);
//                flag++;}// 创建定长线程池threadPool = Executors.newFixedThreadPool(this.threadNum);Downloader4 that = this;for(int i = 1; i <= resPaths.size(); i++){int finalI = i;threadPool.execute(new Runnable() {@Overridepublic void run() {that.download(resPaths.get(finalI -1), targetDir, finalI);System.out.println("[info]" +Thread.currentThread().getName()+",图片下载完毕:" + resPaths.get(finalI -1) + "\n\t  ->" + targetFile.getPath() + "(" + Math.floor(targetFile.length() / 1024) + "kb)");}});}}catch(IOException e){e.printStackTrace();}finally{if(threadPool != null){threadPool.shutdown();}if(reader != null){try{reader.close();}catch(IOException e){e.printStackTrace();}}}}public static void main(String[] args) {
//        int index = 1;Downloader4 downloader2 = new Downloader4();downloader2.start("D:/s_java/se/6-5moreThreadDownloader/downloader/src");
//        String path = downloader2.start("D:/s_java/se/6-5moreThreadDownloader/downloader/src");
//        index = downloader2.download("https://img2.baidu.com/it/u=1567841056,1924556786&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=667", path, index);}/*** 目标目录:D:/game/wzry/mtj* [info]pool-1-thread-1,图片下载完毕:https://img2.baidu.com/it/u=1567841056,1924556786&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=667* 	  ->D:\game\wzry\mtj(4.0kb)* [info]pool-1-thread-3,图片下载完毕:https://img1.baidu.com/it/u=1390259360,3605622436&fm=253&app=138&f=JPEG?w=1534&h=800* 	  ->D:\game\wzry\mtj(4.0kb)* [info]pool-1-thread-2,图片下载完毕:https://img0.baidu.com/it/u=4153860329,1779549628&fm=253&app=138&f=JPEG?w=1570&h=800* 	  ->D:\game\wzry\mtj(4.0kb)* [info]pool-1-thread-1,图片下载完毕:https://img2.baidu.com/it/u=799013572,638024149&fm=253&app=138&f=JPEG?w=1570&h=800* 	  ->D:\game\wzry\mtj(4.0kb)* [info]pool-1-thread-3,图片下载完毕:https://img2.baidu.com/it/u=1702949672,1328662943&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1778* 	  ->D:\game\wzry\mtj(4.0kb)* [info]pool-1-thread-2,图片下载完毕:https://img0.baidu.com/it/u=2015490030,1225562827&fm=253&app=138&f=JPEG?w=800&h=1778* 	  ->D:\game\wzry\mtj(4.0kb)* [info]pool-1-thread-1,图片下载完毕:https://images.pianwan.com/img/h1/h231/img202206241604390_info586X364.png* 	  ->D:\game\wzry\mtj(4.0kb)*/
}

5. 完整版源码

package com.vb.loader;import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class DownloaderDemo {private Integer threadNum = 2;public void download(String url, String targetDir, int index) {InputStream is = null;OutputStream os = null;try{String fileName = "摩托姐" + index + ".png";File targetFile = new File(targetDir + "/" +fileName);if(!targetFile.exists()){targetFile.createNewFile();}URL urlObj = new URL(url);URLConnection connection = urlObj.openConnection();is = connection.getInputStream();os = new FileOutputStream(targetFile);byte[] buffer = new byte[1024];int len = 0;while((len = is.read(buffer)) != -1){os.write(buffer, 0, len);}}catch(IOException e){e.printStackTrace();}finally{try{if(os != null){os.close();}if(is != null){is.close();}}catch(IOException e){e.printStackTrace();}}}public void start(String propDir){System.out.println("propDir:" + propDir);File propFile = new File(propDir + "/config.properties");Properties prop = new Properties();Reader reader = null;String targetDir = "";try{reader = new FileReader(propFile);prop.load(reader);String threadNum = prop.getProperty("thread-num");this.threadNum = Integer.parseInt(threadNum);targetDir = prop.getProperty("target-dir");this.multiDownloaderFile(targetDir, propDir + "/download.txt");}catch (IOException e){e.printStackTrace();}finally{if(reader != null){try {reader.close();} catch (IOException e) {e.printStackTrace();}}}}/*** 从指定文件读取下载地址,批量下载网络资源* @param targetDir    下载后文件的存放目录* @param downloadTxtPath   download文件的路径*/public void multiDownloaderFile(String targetDir, String downloadTxtPath){File targetFile = new File(targetDir);if(!targetFile.exists()){targetFile.mkdirs();System.out.println("自动创建目录:" + targetDir);}System.out.println("目标目录:"+ targetDir);List<String> resPaths = new ArrayList<String>();BufferedReader reader = null;ExecutorService threadPool = null;int flag = 1;try{reader = new BufferedReader(new FileReader(downloadTxtPath));String line = null;while((line = reader.readLine()) != null){resPaths.add(line);}// 创建定长线程池threadPool = Executors.newFixedThreadPool(this.threadNum);DownloaderDemo that = this;for(int i = 1; i <= resPaths.size(); i++){int finalI = i;threadPool.execute(new Runnable() {@Overridepublic void run() {that.download(resPaths.get(finalI -1), targetDir, finalI);System.out.println("[info]" +Thread.currentThread().getName()+",图片下载完毕:" + resPaths.get(finalI -1) + "\n\t  ->" + targetFile.getPath() + "(" + Math.floor(targetFile.length() / 1024) + "kb)");}});}}catch(IOException e){e.printStackTrace();}finally{if(threadPool != null){threadPool.shutdown();}if(reader != null){try{reader.close();}catch(IOException e){e.printStackTrace();}}}}public static void main(String[] args) {DownloaderDemo downloader2 = new DownloaderDemo();downloader2.start("D:/s_java/se/6-5moreThreadDownloader/downloader/src");}
}

目录结构

注:其他资源文件可在1~4章节复制

相关文章:

  • React 中的TypeScript开发范式
  • ubuntu桌面x11异常修复
  • 上位机开发过程中的设计模式体会(2):观察者模式和Qt信号槽机制
  • ubuntu + nginx 1.26 + php7.4 + mysql8.0 调优
  • 机器学习中的优化问题描述
  • Python列表:高效灵活的数据存储与操作指南
  • 讲讲JVM的垃圾回收机制
  • 基于大模型的输尿管下段结石诊疗全流程预测与方案研究
  • 项目课题——智能花盆系统设计
  • 核心机制:面向字节流
  • 业务:资产管理功能
  • Vim 调用外部命令学习笔记
  • 新一代 Rust Web 框架的高性能之选
  • 【数据结构】图算法(代码)
  • 微信小程序中的计算属性库-miniprogram-computed
  • 全新AI驱动Workspace Security 套件发布!Fortinet 电子邮件安全产品矩阵升级
  • docker compose v2版本创建和运行容器
  • 第九章 窗口看门狗(WWDG)
  • 在 macOS 上搭建 Flutter 开发环境
  • 论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(四)
  • 一个云主机可以做多少网站/seo优化排名工具
  • 怎么做网页文件打开别的网站/百度图片识别在线使用
  • wordpress建站多少钱/seo排名优化的网站
  • web service做网站/数据指数
  • 地方信息网站源码/武汉软件测试培训机构排名
  • 怎么给网站做seo优化/广点通投放平台登录