JAVA多线程实现断点续传
断点续传:将下载或上传任务(一个文件或一个压缩包)人为的划分为几个部分,每一个部分采用一个线程进行上传或下载,如果碰到网络故障,可以从已经上传或下载的部分开始继续上传下载未完成的部分,而没有必要从头开始上传下载。用户可以节省时间,提高速度。
RandomAccessFile的四种传输模式
- r 以只读的方式打开文本,也就意味着不能用write来操作文件
- rw 读操作和写操作都是允许的
- rws 每当进行写操作,同步的刷新到磁盘,刷新内容和元数据
- rwd 每当进行写操作,同步的刷新到磁盘,刷新内容
断点续传实现思路:将大文件均分成几块后,每个线程分别处理一块数据的读取和写入。每次写入都要更新记录的日志文件,断网或暂定后重新开始传输时,根据日志文件的信息,可以接着读取写入数据,不用重头开始传输
代码如下(多线程实现断点续传):
/*** 断点续传** @param dataStr 目标文件地址* @param targetStr 存放地址*/public static void breakpointResume(String dataStr, String targetStr) {File dataFile = new File(dataStr);long length = dataFile.length();int threadNum = 4;//指定线程数//每个线程均分文件大小,且向上取整long part = (long) Math.ceil(length / threadNum);//线程减法计数器CountDownLatch countDownLatch = new CountDownLatch(threadNum);Instant beginTime = Instant.now();//记录传输的日志文件File logFile = new File(targetStr + ".log");String[] splitData = null;//不是null就需要断点续传BufferedReader reader = null;try {if (logFile.exists()) {//存在日志文件,需要进行断点续传reader = new BufferedReader(new FileReader(logFile));String data = reader.readLine();splitData = data.split(",");} else {//不存在日志文件,创建日志文件logFile.createNewFile();}Map<Integer, Long> maps = new ConcurrentHashMap<>();for (int i = 0; i < threadNum; i++) {final int k = i;System.out.println("线程正在执行任务:" + k);String[] finalData = splitData;new Thread(() -> {RandomAccessFile inFile = null;RandomAccessFile outFile = null;RandomAccessFile rafLog = null;try {inFile = new RandomAccessFile(dataFile, "r");//读outFile = new RandomAccessFile(targetStr, "rw");//写rafLog = new RandomAccessFile(logFile, "rw");//操作日志文件的流//确定每个线程读取文件的开始和结束的位置,有断点续传就从日志文件取出的位置开始读取inFile.seek(finalData == null ? k * part : Long.parseLong(finalData[k]));//设置每个线程读取的启始位置outFile.seek(finalData == null ? k * part : Long.parseLong(finalData[k]));//设置每个线程写入的启始位置byte[] bytes = new byte[1024 * 10];//每次读取字节大小int len = -1, allLen = 0;while (true) {len = inFile.read(bytes);//从磁盘读取到缓存if (len == -1) { //数据读完,结束break;}//如果不等于 -1,把每次读取的字节累加allLen = allLen + len;//将读取的字节数放入到map中maps.put(k, allLen + (finalData == null ? k * part : Long.parseLong(finalData[k])));//每个线程的绝对偏移量outFile.write(bytes, 0, len);//从缓存写入到磁盘//将map中的字节日志信息数据写入磁盘StringJoiner stringJoiner = new StringJoiner(",");maps.forEach((key, value) -> stringJoiner.add(String.valueOf(value)));//将日志信息写入磁盘rafLog.seek(0);//覆盖之前的日志信息rafLog.write(stringJoiner.toString().getBytes("UTF-8"));/*** 当前线程读取的内容* allLen + (k * part)* 或* allLen + finalData[k] 日志文件里面的偏移量* >=* 下个线程的起始部分((k + 1) * part)* 当前线程就不再读取写入数据,结束任务*/if (allLen + (finalData == null ? k * part : Long.parseLong(finalData[k])) >= (k + 1) * part) {break;}}} catch (IOException e) {e.printStackTrace();} finally {//关流if (null != outFile && null != inFile && null != rafLog) {try {outFile.close();inFile.close();rafLog.close();} catch (IOException e) {e.printStackTrace();}}countDownLatch.countDown();//减一}}).start();}//主线程要等到线程计数器归零,再继续往下执行countDownLatch.await();Instant endTime = Instant.now();System.out.println("总耗时:" + (Duration.between(beginTime, endTime).toMillis()) + "毫秒");//删除日志文件logFile.delete();} catch (Exception e) {e.printStackTrace();} finally {if (null != reader) {try {reader.close();} catch (IOException e) {e.printStackTrace();}}}}
运行如下:
6个多G的资料 >_<
线程正在执行任务:0
线程正在执行任务:1
线程正在执行任务:2
线程正在执行任务:3
总耗时:60039毫秒
CPU 、内存、磁盘都被利用起来了:
内容转自B站up视频
JAVA多线程实现断点续传相关推荐
- java多线程下载_Java实现多线程下载,支持断点续传
多线程下载及断点续传的实现是使用 HTTP/1.1 引入的 Range 请求参数,可以访问Web资源的指定区间的内容.虽然实现了多线程及断点续传,但还有很多不完善的地方. 包含四个类: Downloa ...
- java ftp 断点,java实现ftp断点续传
//import cz.dhl.io.*; //import cz.dhl.ftp.*; import .ftp.*; import .*; import java.applet.*; import ...
- Java 服务器端支持断点续传的源代码
2019独角兽企业重金招聘Python工程师标准>>> Java 服务器端支持断点续传的源代码[支持快车.迅雷](仅支持 HTTP 协议) 网上关于 Java 支持 HTTP 断点续 ...
- Android多线程下载断点续传
先上图看卡结果: GITHUB:Android多线程下载断点续传 下载杵这儿 如图所示点击下载就开始下载,点击停止就会停止再次点击下载就会接着下载了. 设计思路是这样的: 首先通过广播将下载信息传递给 ...
- java多线程查询_java多线程查询
标签: 由于最近工作遇到性能问题,尝试研究用多线程来实现,结果速度快了好几倍 下面是多线程查询的部分代码,提供给大家参考下: 线程类: 带返回值的类要实现Callable接口,具体业务逻辑没有实现,只 ...
- Java 服务器端支持断点续传的源代码【支持快车、迅雷】
Java 服务器端支持断点续传的源代码[支持快车.迅雷](仅支持 HTTP 协议) 网上关于 Java 支持 HTTP 断点续传的文章不少,但关于 Java 服务器端支持 HTTP 断点续传的却比较少 ...
- java多线程下载源码_Java多线程文件分片下载实现的示例代码
多线程下载介绍 多线程下载技术是很常见的一种下载方案,这种方式充分利用了多线程的优势,在同一时间段内通过多个线程发起下载请求,将需要下载的数据分割成多个部分,每一个线程只负责下载其中一个部分,然后将下 ...
- Java 多线程的基本方式
Java 多线程的基本方式 基础实现两种方式: 通过实现Callable 接口方式(可得到返回值):
- Java多线程读取本地照片为二进制流,并根据系统核数动态确定线程数
Java多线程读取图片内容并返回 1. ExecutorService线程池 2. 效率截图 3. 源码 1. ExecutorService线程池 ExecutorService线程池,并可根据系统 ...
最新文章
- 《大话存储》读书笔记一
- 常用的图像增强处理办法
- python3 csv 读入数组_如何将CSV数据读入NumPy中的记录数组?
- mongodb php update,MongoDB文档的更新(php代码实例)
- sklearn 决策树例子_决策树--规则挖掘应用
- 美团信用卡现金分期怎么还?
- 由外而内看敏捷软件开发(上)——从业务视角看敏捷
- 纸筒制作机器人_趣味STEAM教育:如何用“垃圾”制作机器人?
- Visio绘制电路图
- HP服务器固件升级(ILO及bios升级:实操版)
- python 角度变弧度_弧度制和角度值怎么转换?
- hibernate 数据分页显示 及 分页导航栏的设置
- 软考嵌入式系统设计师
- 大数据是什么 有哪些价值
- rust倒地了怎么起来_ggxx出招表
- 成功解决http error 503.the service is unavailable错误
- 混沌工程:分布式系统稳定性的“疫苗”
- python 画心形线 matplotlib
- 服务器繁忙 微信 苹果,iOS 9正式放出 服务器繁忙苹果推荐用户早晨更新
- 太硬核了,我写了一份操作系统词典送给你!