你知道的越多,不知道的就越多,业余的像一棵小草!

成功路上并不拥挤,因为坚持的人不多。

编辑:业余草

juejin.cn/post/6976454072685559822

推荐:https://www.xttblog.com/?p=5221

前言

继续更新,得空记录下之前写得一个需求,欢迎大家前来指教,轻喷????

需求 导出Excel:本身以为是一个简单得导出,但是每行得记录文件中有一列为图片url,需要下载所有记录行对应得图片,然后压缩整个文件夹。

这里只做步骤 4、5 的代码讲解描述,其它也没什么好说得,话不多说上代码。

实现思路

多线程实现使用了「线程池」,Jdk1.8 并发包下的

第一步:得到基础数值

 // 线程数
Integer threadNum = 10;
// 每条线程需要处理的图片数
int dataNum = imageInfoVos.size() / threadNum;
// 写入线程数
List<Integer> threadS = new ArrayList<>();
for(int i=0; i<threadNum; i++){threadS.add(i);
}

首先我们保存了需要下载的图片的 Url 列表,多线程的方式下载我们需要保证每个线程下载的图片不会重复,因此我们需要根据规则来切割保存 Url 列表的集合,从而保证每个线程下载属于自己的任务,上代码 :

 // 接上文代码threadS.stream().map(item -> CompletableFuture.runAsync(() ->{List<Image> theadItem = imageInfoVos.subList(dataNum * item,(item+1)==threadNum?imageInfoVos.size():Math.min(dataNum * (item + 1 ), imageInfoVos.size()));threadDownPic(theadItem,item,dirName);},threadPoolTaskExecutor)).collect(Collectors.toList()).forEach(item ->{try {item.get();}catch (Exception e){log.error("============  多线程down执行等待异常 msg:{} =============", e.getMessage());}
});

这里进行拆分讲解

使用 CompletableFuture.runAsync 走异步方式,遍历 item

如 item=10,也就是线程数为 10,则直接执行 10 次(「有线程池的前提下」)

 // 使用CompletableFuture.runAsync 走异步方式,遍历item// 如item=10,也就是线程数为10,则直接执行10次(有线程池的前提下)threadS.stream().map(item -> CompletableFuture.runAsync(() ->{

「规则」:根据item数值通过 sublist 从开始到结束,截取对应线程所需要下载的 Url列表。

例:dataNum 为每个线程需要完成的下载数如上文 dataNum 为 100 时 如:item=0 dataNum* item(0) =0,Math.min(dataNum * (item + 1 )=100 (item+1)==threadNum?imageInfoVos.size() 此次是为了保证最后一个线程处理最后不足的图片

根据如上规则即可得到每个线程需要下载的图片Url保证不会重复

// 根据item数值通过sublist 从开始到结束,截取对应线程所需要下载的Url列表
// 例:dataNum为每个线程需要完成的下载数如上文 dataNum为100时
// 如:item=0 dataNum* item(0) =0,Math.min(dataNum * (item + 1 )=100
// 根据如上规则即可得到每个线程需要下载的图片Url保证不会重复
// (item+1)==threadNum?imageInfoVos.size() 此次是为了保证最后一个线程处理最后不足的图片
List<ImageInfoVo> theadItem = imageInfoVos.subList(dataNum * item,(item+1)==threadNum?imageInfoVos.size():Math.min(dataNum * (item + 1 ), imageInfoVos.size()));
// theadItem:图片Url  item:所属下标  dirName:写入路径url
threadDownPic(theadItem,item,dirName);

由于执行的异步方式,此处是为了线程池中所有线程都结束才能往下走,执行压缩文件步骤,这里提一嘴,如果没有手动赋予线程池,CompletableFuture 默认使用ForkJoinPool.commonPool,会根据电脑核心数来指定。

比如:我本机未指定就是 7 个线程,执行方法时,会执行完前面 7 个线程任务,才会继续创建 3 个线程继续执行后续未完成的。

threadS.stream().map(item -> CompletableFuture.runAsync(() ->{List<Image> theadItem = imageInfoVos.subList(dataNum * item,(item+1)==threadNum?imageInfoVos.size():Math.min(dataNum * (item + 1 ), imageInfoVos.size()));threadDownPic(theadItem,item,dirName);
},threadPoolTaskExecutor)).collect(Collectors.toList()).forEach(item ->{try {item.get();}catch (Exception e){log.error("============  多线程down执行等待异常 msg:{} =============", e.getMessage());}
});

实测

主要代码也写完了,这种方式真的能提高效率吗?下面我贴几张测试图来说明

多线程图片下载

其实这种方式并没有显著的提高效率,当然这是我本机环境测试的。

「效率是由网速决定,而不是由本机 Cpu 和 io 决定,比如 10M 带宽,一个线程一个一个顺序下载,但速度是 10M,10 个线程,可能每个线程的速度是 1M,结果没有什么两样。相对于网速,多线程带来的 cpu 以及 io 节省的时间几乎可以忽略,瓶颈还是在网速。」

「接口优化点为:提高压缩效率可以不将图片保存到本地而直接压缩文件流」

结尾

我的同事,当然也包括一些网友,总感觉很多知识学习了没有应用的场景。本文从一个实践的真实项目场景出发,教大家使用上 CompletableFuture,线程池等知识点。如果你认为本文代码在实现方式上还有改进的地方,比如本文的线程池可以接合 CountdownLatch 使用等都可以讨论。

水文不易,欢迎大家参与讨论和指出不足的✌

手把手教你线程池配合CompletableFuture实现图片下载并压缩相关推荐

  1. 手把手教你用java完成文件、图片下载

    package Kj; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream ...

  2. 【多线程】优雅使用线程池结合CompletableFuture实现异步编排

    文章目录 参考 1.线程池引入 2.Executors 2.1.概述 2.2.Executors缺陷 3.优雅的创建线程池 3.1.正确挑选方法 3.2.线程池配置类 4.线程池执行流程 5.Comp ...

  3. 手把手教你用Python打造一款批量下载视频并能可视化显示下载进度的下载器

    点击上方"Python爬虫与数据挖掘",进行关注 回复"书籍"即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 桃之夭夭,灼灼其华. /1 前言/ ...

  4. 「云原生 | Docker」手把手教你搭建镜像仓库并上传/下载镜像

    手把手教你搭建镜像仓库 一.选择镜像仓库 二.使用 Docker 官方仓库 1. 注册账号并登录 2. 创建私有仓库 3. 设置私有秘钥 3. 登录 Docker 仓库 4. 上传镜像到 Docker ...

  5. 效率工具 001 | 手把手教你满速(不限速)下载百度网盘文件

    百度网盘,曾用名百度云(Baidu Cloud),是百度推出的一项个人云存储服务,覆盖中国大陆各大主流计算机和手机操作系统,包含Web版.Windows版.Mac版.Android版和iPhone版. ...

  6. Blender图解教程:手把手教你做一个马里奥金币 之 图片转法线贴图法(附模型下载)

    <Blender图解教程:手把手教你做一个马里奥金币 之 比较传统的方法>介绍了一种用Blender制作法线贴图的流程,本文介绍一种更加省事的方法. 步骤 效果图 概要 步骤 1. 建模 ...

  7. android线程池断点续传,Android之多线程下载及断点续传

    今天我们来接触一下多线程下载,当然也包括断点续传,我们可以看到 很多下载器,当开通会员的时候下载东西的速度就变得快了许多,这是为什么呢?这就是跟今天讲的多线程有关系了,其实就是多开了几个线程一起下载罢 ...

  8. 手把手教你如何在安卓中使图片进行旋转

    下面介绍一些关于在Android中,使图片进行旋转的一些方法,当然这里主要介绍旋转的,如果有其他的动画效果,可以类似的进行修改:: 方法一: 1.首先在res文件夹下创建一个名字为anim的文件夹,名 ...

  9. html显示本地磁盘 图片,手把手教你为本地磁盘增添背景图片(图解)

    一:准备好一张作为背景的图片,放在一个自己能够找到的文件中.然后打开想要设置的磁盘,这里选择的是C盘.右单击磁盘内的空白处,选择新建-文本文档. 二:点击打开文本文档,将下面的代码复制进文本文档内,然 ...

最新文章

  1. Python3可变字符串代码实现
  2. c++中stack容器
  3. const 和 #define 区别总结
  4. 大数据日志分析项目架构
  5. 区块链:5、匿名性和隐私性
  6. PLC 控制三相异步电动机正反转实验
  7. Android设置屏幕亮度的两种方式
  8. ubuntu多显示器单触摸屏校准
  9. Shawn邀您共读《WebGL编程指南》| GLSL ES篇
  10. 帝国CMS二次开发入门教程
  11. 谷歌 draco学习 一 压缩格网信息
  12. tcl c语言笔试题,TCL 2019校园招聘备战-求职应聘指南(笔试真题面试经验).pdf
  13. ssms 导出mysql_怎样使用SSMS管理器导出数据表 用SSMS管理器导出数据表的方法
  14. 《好妈妈胜过好老师》书摘
  15. java excel 多列排序,《excel表格调取行和列的数据》 excel列排序的时候怎么让所有行的信息跟着排(其它的非数据行)...
  16. LTE CA带宽能力(CA bandwidth classes)规定了聚合带宽限制,见36.101中表格Table 5.6A-1
  17. Life is short(人生如此短暂)
  18. 曲径通幽——遇见未知的你
  19. 物致DIY:OpenMV4——比OpenMV3更快,更高,更强的图像识别DIY神器来了!
  20. 低代码助力生产管理:ERP生产管理系统

热门文章

  1. pandas数据拼接
  2. Ubuntu 自带截图工具快捷键盘
  3. 做人做事箴言录(3)
  4. Unity 回合制战斗系统(中级篇)-血条和伤害数值
  5. 儿子懂得心痛他爸爸了
  6. 2016机器学习大盘点(第3篇)
  7. Kermit,Xmodem,1K-Xmodem,Ymodem,Zmodem传输协议小结
  8. 零基础怎么系统学习大数据?
  9. 甜糖官方爱快docker
  10. 有关学术界的治理-来自学术道德通论课程作业