前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用多线程实现文件的下载_多线程写同一个文件

使用多线程实现文件的下载_多线程写同一个文件

作者头像
全栈程序员站长
发布2022-11-04 10:40:54
8500
发布2022-11-04 10:40:54
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。

首先,我们要下载一个文件,可以通过多线程的方式快速下载!!!

多线程下载文件的步骤:

1、首先要知道请求下载的服务器支持断点下载,即支持request头信息中的Range的设置

2、然后通过对请求头设置

代码语言:javascript
复制
httpConnection.setRequestProperty("Range","bytes="+startIndex+"-"+endIndex);

3、然后获取整个文件的大小

4、在本地创建一个一样大的文件,然后根据线程数进行分配startIndex和endIndex

5、线程下载的同时,使用RandomAccessFile对所下载的内容随机对应写入文件

这里要注意,你所访问的文件在服务器端必须吧能够返回Content-Length这个参数才行!!!

完整的示例代码:

代码语言:javascript
复制
package cn.ljxwtl.plugin.common.util;
import com.alibaba.fastjson.JSON;
import cn.ljxwtl.plugin.engine.EngineAssistant;
import org.apache.commons.io.IOUtils;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.RandomAccess;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ThreadPoolExecutor;
/**
* @author: wtl
* @License: (C) Copyright 2022, wtl Corporation Limited.
* @Contact: 1050100468@qq.com
* @Date: 2022/4/1 10:50
* @Version: 1.0
* @Description:
*/
public class DownloadFileUtil {
public static void downloadFileWithMultiThread(String url,String filePath,Runnable runnable) throws Exception {
List<long[]> perThreadDownloadFileOffset = getPerThreadDownloadFileOffset(url, 1024* 1024);
ThreadPoolExecutor threadPoolExecutor = EngineAssistant.THREAD_POOL_EXECUTOR;
int size = Objects.requireNonNull(perThreadDownloadFileOffset).size();
CyclicBarrier cyclicBarrier = new CyclicBarrier(size, ()->{
if (null != runnable){
runnable.run();
}
});
URL openUrl = new URL(url);
for (int i = 0; i< size; i++){
int finalI = i;
new Thread(()->{
try {
HttpURLConnection urlConnection = (HttpURLConnection) openUrl.openConnection();
urlConnection.setRequestProperty("Range","bytes="+perThreadDownloadFileOffset.get(finalI)[0]+"-"+perThreadDownloadFileOffset.get(finalI)[1]);
urlConnection.setDoInput(true);
BufferedInputStream bufferedInputStream = new BufferedInputStream(urlConnection.getInputStream());
int length = -1;
byte [] buffer = new byte[102400];
RandomAccessFile randomAccessFile = new RandomAccessFile(filePath,"rw");
System.out.println(perThreadDownloadFileOffset.get(finalI)[1] - perThreadDownloadFileOffset.get(finalI)[0]);
randomAccessFile.seek(perThreadDownloadFileOffset.get(finalI)[0]);
int perSize = 0;
while ((length = bufferedInputStream.read(buffer))!=-1){
randomAccessFile.write(buffer,0,length);
perSize +=length;
}
randomAccessFile.close();
System.out.println(perThreadDownloadFileOffset.get(finalI)[0] + "------------------" +(perThreadDownloadFileOffset.get(finalI)[0] +  perSize));
} catch (Exception e) {
e.printStackTrace();
}
finally {
try {
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}
/**
* 获取每个线程所需要的File的offset
* @param url url地址
* @param perThreadDealFileSize 每个线程处理的文件下载大小
* @return List<int []>
*/
private static List<long []> getPerThreadDownloadFileOffset(String url,long perThreadDealFileSize){
URLConnection urlConnection = null;
try {
urlConnection = new URL(url).openConnection();
long contentLengthLong = urlConnection.getContentLengthLong();
List<long[]> threadOffsetDatas = new ArrayList<>();
long size = (long) Math.ceil(contentLengthLong * 1.0 / perThreadDealFileSize);
for (int i = 0; i < size; i++) {
long start = i * perThreadDealFileSize;
long end = (i + 1) * perThreadDealFileSize - 1;
if (i == size - 1) {
start = i * perThreadDealFileSize;
end = contentLengthLong;
}
threadOffsetDatas.add(new long[]{start,end});
}
System.out.println(JSON.toJSONString(threadOffsetDatas));
return threadOffsetDatas;
}
catch (Exception e){
e.printStackTrace();
}
return null;
}
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/195242.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年9月10日 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 首先,我们要下载一个文件,可以通过多线程的方式快速下载!!!
    • 多线程下载文件的步骤:
    • 这里要注意,你所访问的文件在服务器端必须吧能够返回Content-Length这个参数才行!!!
    相关产品与服务
    云服务器
    云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档