问题记录:线程池批量下载文件

在一个视频网上找到了喜欢的在线视频资源,没有下载按钮,只能自己下载了,看了 一下network,是ts分片的文件,好在是命名挺规范的,都是 xxxx + index + .ts的格式,方便了 我下载。
一开始我用单线程下载,下了半天只下了200个 分片,总共有800个,因此想到了线程池,一直以为我是会用线程池的,结果才发现了自己的不足,记录一下。

构造器

        /*和数据库连接池很像*/
        ThreadPoolExecutor pool = new ThreadPoolExecutor(1, // 小于corePoolSize时即使其他线程空闲也会创建
                5, // 如果当前线程都忙,但是小于总线程,会创建新的
                1000, // 空闲(非核心)线程存活时间
                TimeUnit.MINUTES,
                new ArrayBlockingQueue<>(5)); // 如果使用synchronousQueue 线程最多只能达到corePoolSize


举个例子,我使用了
ExecutorService service = Executors.newFixedThreadPool(4);
内部就是:
public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>()); // 任务队列是无界的,因此不需要在意拒绝策略。
    }
说到 拒绝 策略,一共有4种
 /**
         * maximumPoolSize有限,等待任务队列使用的是有界队列,倘若是linkedBlockQueue总是排队
         * 默认AbortPolicy 抛出异常
         * Discard 忽略新任务, 不报错
         * DiscardOld 取消旧任务
         * CallerRunsPolicy 在提交线程中执行任务
         */

下面进入正题

异常

我的程序借用了httpclient

HttpClient httpClient= new DefaultHttpClient();
ExecutorService service = Executors.newFixedThreadPool(4);
        Collection<Callable<Integer>> futureTasks = new LinkedList<>();
        for (int i = 1; i <= totalPierce; i++) {
            final int v = i;
            futureTasks.add(() -> {
                download(httpClient, v);
                return v;
            });
        }
        List<Future<Integer>> futureList = service.invokeAll(futureTasks);
private static void download(HttpClient client, int i) {
        System.out.println("连接" + i + "ts");
        HttpGet httpget = new HttpGet(makeURL(i));
        try {
            HttpResponse response = client.execute(httpget);
            HttpEntity entity = response.getEntity();
            String file = "F:\\seg-" + i + ".ts";
            FileOutputStream os = new FileOutputStream(file);
            entity.writeTo(os);
            os.close();
            System.out.println("完成" + i);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

执行结果也特别奇怪,先输出1,2,3,4,阻塞 一段时间,然后 一股脑的输出连接直到 totalPierce.但是没有显示完成的,开了VisualVM,线程都是正常的,我就猜想 是不是哪里 出现问题,搜了 一下,参考了这篇文章:
连接
按照前辈所说,不适合设置异常处理类来处理 ,而且我这里只是 个人小玩具 ,有三个办法:

  1. 异常处理直接打印到控制台,但是如果多个线程同时打印 ,输出可能是乱 的
  2. 打印到日志,我比较懒,不想再拉配置文件和添加依赖,pass
  3. 对于结果进行get,在get处进行异常处理

原来如此,如果futureTask异常,future.get时是会 抛出的!
添加如下代码 :

for (Future f :
                futureList) {
            try {
                f.get();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }

        }

这才发现 defaultHttpclient不是线程安全的!
因此改用

PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
        cm.setMaxTotal(100);

        CloseableHttpClient httpClient = HttpClients.custom()
                .setConnectionManager(cm)
                .build();

暂时没有问题,但是还没有完全好,我仍然少考虑了很多东西,比如异常的分片需要 重试?下载速度仍然没有达到很高,追忆前辈们proxyee-down IDM等等的下载工具,真是高山仰止,还需努力

附上httpClient依赖:

		<dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.3</version>
        </dependency>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
zhuaxia 可以从 xiami.com 和 music.163.com 下载 MP3 文件和音频。zhuaxia 是一个基于命令行的虾米音乐 ( www.xiami.com 以下简称[虾])和网易云音乐( music.163.com 以下简称[易]) 多线程批量下载工具zhuaxia 的开发调试环境:python 2.7.6依赖requests modulemutagen modulebeautifulsoup4 module特性自动识别解析URL. 目前支持:[虾] 歌曲,专辑,精选集,用户收藏[todo], 歌手热门[易] 歌曲,专辑,歌单,歌手热门下载歌手热门歌曲:数量可配置( 海外IP下载xiami资源" 一节加入实验性-p选项,尝试解决频繁请求被服务器ban的问题中英文命令行界面. 配置项 lang=en|cn 默认中文(cn)InstallationArchlinux 用户, zhuaxia可以从AUR中获取稳定版本(master branch):稳定版本:yaourt -S zhuaxia最新git版本(bleeding branch):yaourt -S zhuaxia-git其他用户:sudo python setup.py installUsage配置文件, 第一次运行zx后, 在$HOME/.zhuaxia/ 会有配置文件 zhuaxia.conf 配置参数有中文说明使用:zhuaxia (抓虾) -- 抓取[虾米音乐]和[网易云音乐]的 mp3 音乐 [CONFIG FILE:]   $HOME/.zhuaxia/zhuaxia.conf [OPTIONS]      -H : 首选HQ质量(320kbps),          > 虾米音乐  网易音乐 <             -无需特殊要求,直接下载高音质资源     -p : (实验性选项)使用代理池下载         在下载/解析量大的情况下,目标服务器会对禁止频繁的请求,所以zhuaxia可以自动获取         代理来解析和下载资源。因为获取的代理速度/可靠性不一,下载可能会缓慢或不稳定。     -h :显示帮助     -f :从文件下载     -v :显示版本信息 [USAGE]      zx [OPTION]          : 下载指定URL资源, 抓虾自动识别链接, 支持             - [虾] 歌曲,专辑,精选集,用户收藏,艺人TopN             - [易] 歌曲,专辑,歌单,艺人TopN         例子:            zx "http://www.xiami.com/space/lib-song/u/25531126"           zx "http://music.163.com/song?id=27552647"     zx [OPTION] -f           : 多个URL在一个文件中,每个URL一行。 URLs可以是混合[虾]和[易]的不同类型音乐资源。例子:           $ cat /tmp/foo.txt             http://music.163.com/artist?id=5345             http://www.xiami.com/song/1772130322             http://music.163.com/album?id=2635059             http://www.xiami.com/album/32449           $ zx -f /tmp/foo.txtProxy setting海外IP下载xiami资源xiami.com屏蔽了海外ip的http请求。在配置文件中添加(如果不存在的话)xiami.proxy.http=ip:port 可以让zhuaxia通过代理来解析xiami资源。 例如:xiami.proxy.http=127.0.0.1:8080这里ip:port构成的http代理是国内的代理服务器。 如果你的机器已经是国内的ip,请注释或删除这个选项。获取国内代理的简单方法:到http://proxy-list.org/ 搜索China的代理就好。Screenshotsdownloading (gif animation) parse input file parse url 标签:zhuaxia

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值