mysql 线程池 下载_java线程池实现批量下载文件
本文实例为大家分享了java线程池实现批量下载文件的具体代码,供大家参考,具体内容如下
1 创建线程池
package com.cheng.webb.thread;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadUtil {
/**
* 创建批量下载线程池
*
* @param threadSize 下载线程数
* @return ExecutorService
*/
public static ExecutorService buildDownloadBatchThreadPool(int threadSize) {
int keepAlive = 0;
String prefix = "download-batch";
ThreadFactory factory = ThreadUtil.buildThreadFactory(prefix);
return new ThreadPoolExecutor(threadSize,
threadSize,
keepAlive,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(threadSize),
factory);
}
/**
* 创建自定义线程工厂
*
* @param prefix 名称前缀
* @return ThreadFactory
*/
public static ThreadFactory buildThreadFactory(String prefix) {
return new CustomThreadFactory(prefix);
}
/**
* 自定义线程工厂
*/
public static class CustomThreadFactory implements ThreadFactory {
private String threadNamePrefix;
private AtomicInteger counter = new AtomicInteger(1);
/**
* 自定义线程工厂
*
* @param threadNamePrefix 工厂名称前缀
*/
CustomThreadFactory(String threadNamePrefix) {
this.threadNamePrefix = threadNamePrefix;
}
@Override
public Thread newThread(Runnable r) {
String threadName = threadNamePrefix + "-t" + counter.getAndIncrement();
return new Thread(r, threadName);
}
}
}
2 批量下载文件
package com.cheng.webb.thread;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
/**
* 文件下载类
*
* @author shucheng
* @creation 2019年1月30日下午4:41:32
*/
public class DownloadUtil {
private static Logger logger = LoggerFactory.getLogger(DownloadUtil.class);
/**
* 下载线程数
*/
private static final int DOWNLOAD_THREAD_NUM = 14;
/**
* 下载线程池
*/
private static ExecutorService downloadExecutorService = ThreadUtil
.buildDownloadBatchThreadPool(DOWNLOAD_THREAD_NUM);
/**
* 文件下载
*
* @param fileUrl
* 文件url,如:https://img3.doubanio.com//view//photo//s_ratio_poster//public//p2369390663.webp
* @param path
* 存放路径,如: /opt/img/douban/my.webp
*/
public static void download(String fileUrl, String path) {
// 判断存储文件夹是否已经存在或者创建成功
if (!createFolderIfNotExists(path)) {
logger.error("We can't create folder:{}", getFolder(path));
return;
}
InputStream in = null;
FileOutputStream out = null;
try {
URL url = new URL(fileUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
// 2s
conn.setConnectTimeout(10000);
in = conn.getInputStream();
out = new FileOutputStream(path);
int len;
byte[] arr = new byte[1024 * 1000];
while (-1 != (len = in.read(arr))) {
out.write(arr, 0, len);
}
out.flush();
conn.disconnect();
} catch (Exception e) {
logger.error("Fail to download: {} by {}", fileUrl, e.getMessage());
} finally {
try {
if (null != out) {
out.close();
}
if (null != in) {
in.close();
}
} catch (Exception e) {
// do nothing
}
}
}
/**
* 创建文件夹,如果文件夹已经存在或者创建成功返回true
*
* @param path
* 路径
* @return boolean
*/
private static boolean createFolderIfNotExists(String path) {
String folderName = getFolder(path);
if (folderName.equals(path)) {
return true;
}
File folder = new File(getFolder(path));
if (!folder.exists()) {
synchronized (DownloadUtil.class) {
if (!folder.exists()) {
return folder.mkdirs();
}
}
}
return true;
}
/**
* 获取文件夹
*
* @param path
* 文件路径
* @return String
*/
private static String getFolder(String path) {
int index = path.lastIndexOf("/");
return -1 != index ? path.substring(0, index) : path;
}
/**
* 下载资源
*
* issue: 线程池创建过多
*
* 最大批量下载为5,请知悉
*
* @param resourceMap
* 资源map, key为资源下载url,value为资源存储位置
*/
public static void batch(Map resourceMap) {
if (resourceMap == null || resourceMap.isEmpty()) {
return;
}
try {
List keys = new ArrayList<>(resourceMap.keySet());
int size = keys.size();
int pageNum = getPageNum(size);
for (int index = 0; index < pageNum; index++) {
int start = index * DOWNLOAD_THREAD_NUM;
int last = getLastNum(size, start + DOWNLOAD_THREAD_NUM);
final CountDownLatch latch = new CountDownLatch(last - start);
// 获取列表子集
List urlList = keys.subList(start, last);
for (String url : urlList) {
// 提交任务
Runnable task = new DownloadWorker(latch, url, resourceMap.get(url));
downloadExecutorService.submit(task);
}
latch.await();
}
} catch (Exception e) {
logger.error("{}", e);
}
logger.info("Download resource map is all done");
}
/**
* 获取最后一个元素
*
* @param size
* 列表长度
* @param index
* 下标
* @return int
*/
private static int getLastNum(int size, int index) {
return index > size ? size : index;
}
/**
* 获取划分页面数量
*
* @param size
* 列表长度
* @return int
*/
private static int getPageNum(int size) {
int tmp = size / DOWNLOAD_THREAD_NUM;
return size % DOWNLOAD_THREAD_NUM == 0 ? tmp : tmp + 1;
}
/**
* 下载线程
*/
static class DownloadWorker implements Runnable {
private CountDownLatch latch;
private String url;
private String path;
DownloadWorker(CountDownLatch latch, String url, String path) {
this.latch = latch;
this.url = url;
this.path = path;
}
@Override
public void run() {
logger.debug("Start batch:[{}] into: [{}]", url, path);
DownloadUtil.download(url, path);
logger.debug("Download:[{}] into: [{}] is done", url, path);
latch.countDown();
}
}
}
3 测试批量下载文件
package com.cheng.webb.thread;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import com.alibaba.fastjson.JSON;
public class DownLoadTest {
String json = "{\r\n"
+ " \"http://www.xxx.com/111/123.mp4\":\"myFile/111/123.mp4\",\r\n"
+ " \"http://www.xxx.com/111/124.mp4\":\"myFile/111/124.mp4\",\r\n"
+ " \"http://www.xxx.com/111/125.mp4\":\"myFile/111/125.mp4\"\r\n"
+ "}";
@SuppressWarnings("unchecked")
@Test
public void test() {
Map map = new HashMap<>();
Map resMap = JSON.parseObject(json, map.getClass());
int times = 1;
for (int index = 0; index < times; index++) {
DownloadUtil.batch(resMap);
}
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
mysql 线程池 下载_java线程池实现批量下载文件相关推荐
- [Windows] 哔哩下载姬—B站视频批量下载
哔哩下载姬 简介:哔哩下载姬是一款下载哔哩哔哩视频的免费软件.适用:windows系统文件大小:18.7 MB 特点: 1.无需登录即可下载. 2.可以多线程,多任务同时下载.(最高支持10线程,10 ...
- python怎么批量下载年报_使用Python批量下载Wind数据库中的PDF报告
原标题:使用Python批量下载Wind数据库中的PDF报告 背景 最近小编出于工作需要,准备在Wind金融数据终端批量下载上市公司2019年第一季度业绩预告.通过相关的条件检索,发现其相关数据有近百 ...
- 自媒体批量下载短视频软件,批量下载短视频有诀窍
自媒体批量下载短视频软件,批量下载短视频有诀窍,现在随着短视频的爆火,越来越多的自媒体人和公司都注意到短视频这个平台流量有多大,短视频很容易变现也很容易引流,接下来我们来看看自媒体批量下载短视频软件有 ...
- vue-qr 二维码 添加logo 下载单个二维码 批量下载二维码并打包
使用 vue-qr 生成二维码并可以添加logo 逻辑: 1.下载二维码生成插件 这里用的是qrcode 2.下载二维码 使用html2canvas(其实解释一个截图工具)将标签截图并下载下来 3. ...
- mysql服务器多线程模型_java 线程池、多线程并发实战(生产者消费者模型 1 vs 10) 附案例源码 - 陈彦斌 - 博客园...
导读 前二天写了一篇<Java 多线程并发编程>点我直达,放国庆,在家闲着没事,继续写剩下的东西,开干! 线程池 为什么要使用线程池 例如web服务器.数据库服务器.文件服务器或邮件服务器 ...
- java线程不执行_java线程池,阿里为什么不允许使用Executors?
带着问题 阿里Java代码规范为什么不允许使用Executors快速创建线程池? 下面的代码输出是什么? ThreadPoolExecutor executor = new ThreadPoolExe ...
- java线程池执行器_Java线程池ThreadPoolExecutor的使用
Java线程池ThreadPoolExecutor的使用 ThreadPoolExecutor就是我们用来实现线程的一个执行器,它实现了Excutor和ExecutorService接口.Excuto ...
- java 线程池数量_java线程池及创建多少线程合适
java线程池 1.以下是ThreadPoolExecutor参数完备构造方法: public ThreadPoolExecutor(int corePoolSize,int maximumPoolS ...
- java线程池概念_Java 线程池概念、原理、简单实现
线程池的思想概述 我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结東了,这样频繁创建线程就会大大降低系 ...
最新文章
- GBDT Xgboost LightGBM区别与联系
- 【总结】IE6,IE7,IE8,Firefox兼容的css hack 补充!
- 相声演员侯耀文突发疾病去世享年59岁 深切怀念
- 示波器1m和50欧姆示阻抗匹配_阻抗匹配,示波器,50欧姆电阻,他们之间是什么关系?(第一回)...
- 前端学习(1466):表格案例其他效果演示
- 使用sqoop从Oracle或mysql抽取数据到HDFS遇到的报错及解决
- H2O Wave教程---基于浏览器的实时显示工具---教程01
- 小程序:版本更新后获取用户信息变更
- 计算机双硬盘安装需要跳线吗,双硬盘安装图文教程
- PROSOFT模块MVI56E-MNETC、MVI56-PDPMV1、PTQ-PDPMV1、AN-X2-AB-DHRIO、MVI56-MBP、MVI56-MNETR、MVI56-MNET
- java整人的代码_「vbs代码」vbs表白代码+整人代码,抖音vbscript表白代码 - seo实验室...
- web前端之HTML常用标签
- 大学生对于繁体字的态度与认知情况调查
- 互联网大厂数据分析面试常见问题及解法,建议收藏
- html半透明遮罩,如何制作网页半透明遮罩效果
- 【Gem5】有关gem5模拟器的资料导航
- 【JavaScript】节点的常用属性和方法
- 软件测试之自动化测试Pytest教程
- 【JavaScript】
- NPOI 设置EXCEL单元格格式为 数值
热门文章
- 谭浩强c语言规范化的指数形式,C语言程序设计谭浩强第四期末复习重点.docx
- 继续教育统考计算机和英语难度怎么样,网络教育英语统考90分的难度怎么样
- 【剑指offer - C++/Java】7、斐波那契数列
- 【常见笔试面试算法题12续集四】动态规划算法案例分析4 LCS练习题练习题(最长公共子序列的长度)
- 【AtCoder Regular Contest 082】Derangement
- android 多线程断点续传下载 三
- iptables禁止端口和开放端口
- python-pass
- ASP.NET Web Froms开发模式中实现程序集的延迟加载
- 基于三值图像的车牌识别测试程序发布