本文实例为大家分享了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线程池实现批量下载文件相关推荐

  1. [Windows] 哔哩下载姬—B站视频批量下载

    哔哩下载姬 简介:哔哩下载姬是一款下载哔哩哔哩视频的免费软件.适用:windows系统文件大小:18.7 MB 特点: 1.无需登录即可下载. 2.可以多线程,多任务同时下载.(最高支持10线程,10 ...

  2. python怎么批量下载年报_使用Python批量下载Wind数据库中的PDF报告

    原标题:使用Python批量下载Wind数据库中的PDF报告 背景 最近小编出于工作需要,准备在Wind金融数据终端批量下载上市公司2019年第一季度业绩预告.通过相关的条件检索,发现其相关数据有近百 ...

  3. 自媒体批量下载短视频软件,批量下载短视频有诀窍

    自媒体批量下载短视频软件,批量下载短视频有诀窍,现在随着短视频的爆火,越来越多的自媒体人和公司都注意到短视频这个平台流量有多大,短视频很容易变现也很容易引流,接下来我们来看看自媒体批量下载短视频软件有 ...

  4. vue-qr 二维码 添加logo 下载单个二维码 批量下载二维码并打包

    使用 vue-qr 生成二维码并可以添加logo 逻辑: 1.下载二维码生成插件 这里用的是qrcode 2.下载二维码 使用html2canvas(其实解释一个截图工具)将标签截图并下载下来 3. ...

  5. mysql服务器多线程模型_java 线程池、多线程并发实战(生产者消费者模型 1 vs 10) 附案例源码 - 陈彦斌 - 博客园...

    导读 前二天写了一篇<Java 多线程并发编程>点我直达,放国庆,在家闲着没事,继续写剩下的东西,开干! 线程池 为什么要使用线程池 例如web服务器.数据库服务器.文件服务器或邮件服务器 ...

  6. java线程不执行_java线程池,阿里为什么不允许使用Executors?

    带着问题 阿里Java代码规范为什么不允许使用Executors快速创建线程池? 下面的代码输出是什么? ThreadPoolExecutor executor = new ThreadPoolExe ...

  7. java线程池执行器_Java线程池ThreadPoolExecutor的使用

    Java线程池ThreadPoolExecutor的使用 ThreadPoolExecutor就是我们用来实现线程的一个执行器,它实现了Excutor和ExecutorService接口.Excuto ...

  8. java 线程池数量_java线程池及创建多少线程合适

    java线程池 1.以下是ThreadPoolExecutor参数完备构造方法: public ThreadPoolExecutor(int corePoolSize,int maximumPoolS ...

  9. java线程池概念_Java 线程池概念、原理、简单实现

    线程池的思想概述 我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结東了,这样频繁创建线程就会大大降低系 ...

最新文章

  1. GBDT Xgboost LightGBM区别与联系
  2. 【总结】IE6,IE7,IE8,Firefox兼容的css hack 补充!
  3. 相声演员侯耀文突发疾病去世享年59岁 深切怀念
  4. 示波器1m和50欧姆示阻抗匹配_阻抗匹配,示波器,50欧姆电阻,他们之间是什么关系?(第一回)...
  5. 前端学习(1466):表格案例其他效果演示
  6. 使用sqoop从Oracle或mysql抽取数据到HDFS遇到的报错及解决
  7. H2O Wave教程---基于浏览器的实时显示工具---教程01
  8. 小程序:版本更新后获取用户信息变更
  9. 计算机双硬盘安装需要跳线吗,双硬盘安装图文教程
  10. PROSOFT模块MVI56E-MNETC、MVI56-PDPMV1、PTQ-PDPMV1、AN-X2-AB-DHRIO、MVI56-MBP、MVI56-MNETR、MVI56-MNET
  11. java整人的代码_「vbs代码」vbs表白代码+整人代码,抖音vbscript表白代码 - seo实验室...
  12. web前端之HTML常用标签
  13. 大学生对于繁体字的态度与认知情况调查
  14. 互联网大厂数据分析面试常见问题及解法,建议收藏
  15. html半透明遮罩,如何制作网页半透明遮罩效果
  16. 【Gem5】有关gem5模拟器的资料导航
  17. 【JavaScript】节点的常用属性和方法
  18. 软件测试之自动化测试Pytest教程
  19. 【JavaScript】
  20. NPOI 设置EXCEL单元格格式为 数值

热门文章

  1. 谭浩强c语言规范化的指数形式,C语言程序设计谭浩强第四期末复习重点.docx
  2. 继续教育统考计算机和英语难度怎么样,网络教育英语统考90分的难度怎么样
  3. 【剑指offer - C++/Java】7、斐波那契数列
  4. 【常见笔试面试算法题12续集四】动态规划算法案例分析4 LCS练习题练习题(最长公共子序列的长度)
  5. 【AtCoder Regular Contest 082】Derangement
  6. android 多线程断点续传下载 三
  7. iptables禁止端口和开放端口
  8. python-pass
  9. ASP.NET Web Froms开发模式中实现程序集的延迟加载
  10. 基于三值图像的车牌识别测试程序发布