美文网首页
确保自然顺序分片上传文件

确保自然顺序分片上传文件

作者: 奥创没电了 | 来源:发表于2019-12-13 11:52 被阅读0次

项目中涉及视频文件上传,相关服务端给的主要接口是 创建上传文件——分片上传文件流,一个大文件按照一定的大小分割每次上传这分割一部分,就需要多线程处理。

##
ThreadPoolExecutor executor = new     ScheduledThreadPoolExecutor(count);
  for (int i = 0; i < count; i++) {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                // do something
            }
        });
    }

  //指定位置分片文件流  (读取文件的指定范围)
  //文件上传读流方式有 写入其他参数的multipart/form-data,也有只要文件流的    application/octet-stream,此处用application/octet-stream,只读取文件流。

   ByteArrayOutputStream dos = null;
    try {
        dos = new ByteArrayOutputStream();
        File file = new File(filePath);
        RandomAccessFile raf = new RandomAccessFile(file, "r");
        long fileLength = file.length();
        long startPosition = 0L;
        int blockSize = videoResult.blocksize;
        int total_block = videoResult.total_block;
        int current_block = videoResult.current_block;

        startPosition = (current_block - 1 ) * blockSize;
        long endPosition = (startPosition + blockSize) >= fileLength ? fileLength : (startPosition + blockSize);
        raf.seek(startPosition);
                blockSize+"=="+total_block+"=="+raf.getFilePointer());
        int read = 0;
        byte[] bytes = new byte[1024];
        while (raf.getFilePointer() < endPosition && (read = raf.read(bytes)) != -1){
             dos.write(bytes,0,read);
        }
        return dos.toByteArray();
    }catch (Exception e){
        return null;
    }finally {
        if(dos != null){
            try {
                dos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

经过上传测试,小文件正常,大点的文件,由于开启多个线程,执行的顺序随机性的在某个位置发生错乱,即开启多线程后,线程的执行是无法控制的,服务端接收的分片是无序的,就给合并文件造成了困难。当然理论上,这种按多线程同时执行,上传速度显然更快,合并文件也可以有其他方式正常完成。但是目前,本模块服务端设计如此,就是需要确保开启多线程,线程任务按自然顺序进行,按此需求模型,经过查找资料,引入Semaphore,指定Semaphore semaphore = new Semaphore(1); 单通道执行。一个线程执行完开放通道执行下一个

  executors = new ScheduledThreadPoolExecutor(remainCount);
    Semaphore[] syncObjects = new Semaphore[remainCount];
    for(int i = 0; i < remainCount; i++){
        syncObjects[i] = new Semaphore(1);
        try {
            if (i != remainCount - 1){
                syncObjects[i].acquire();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

//保证 分片自然顺序  分片从1开始
  //此处 
  int startBlock = 1;
  //循环中 total_block 就要 加 1;
  total_block += 1;
    for (int i = startBlock; i < total_block; i++) {
    //syncObjects 索引从0开始,此处就要再减去 total_block加上的 1
        final Semaphore lastSemphore = i == startBlock ? syncObjects[total_block - 1 - 1] : syncObjects[i - 1 - startBlock];
        final Semaphore currentSemphore = syncObjects[i - startBlock];
        VideoResult.Result result = new VideoResult.Result(subResult);
        result.current_block = i;
        final VideoResult.Result paramResult = result;
        executors.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    lastSemphore.acquire();
                    uploadFilePartRequest(paramResult);
                    currentSemphore.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }

这个lastSemphore 和currentSemphore 就是每次执行的上一个信号通道,和当前的通道。
线程执行前都是默认锁定


初始默认为除了最后一个其他都锁定占用通道.png

执行开始,上一个锁定,当前的执行完释放。
第一次为最后一个锁定,第一次执行完第一个再释放。
这样就保证了线程池循环开启线程执行时能够保证自然顺序,即和循环的顺序一致。

  PS:查资料后这样使用是可以实现需求效果,然而其根本原理,和加锁的区别,目前属实不是十分清楚。2019.12.13 11:50

相关文章

  • 确保自然顺序分片上传文件

    项目中涉及视频文件上传,相关服务端给的主要接口是 创建上传文件——分片上传文件流,一个大文件按照一定的大小分割每次...

  • 文件分片上传.md

    文件分片上传 文件分片上传的总体思路是 先将文件通过blob.slice()方法将文件切割成多个分片。然后循环上传...

  • 阿里oss文件分片上传

    OSS文件分片上传 依赖 基础参数dto 具体上传方法 小文件上传 大文件上传,分片oss自己处理 处理逻辑:前段...

  • webuploader前端分片上传

    前端分片上传附件 分片上传定义: 所谓的分片上传,就是将所要上传的文件,按照一定的大小,将整个文件分隔成多个数据块...

  • JS分片上传

    JS分片上传 //分片上传 function ScarecrowPatchUpload (uploadPath, ...

  • js文件分片上传

    知识点:File,Blob,FileReader,hash,promisify,async, await 文件Fi...

  • 分片上传文件处理

    此需要基于webuploader.js插件 1. 前端代码 2. 后端代码 3. 控制器代码

  • 大文件分片上传

    转载https://mp.weixin.qq.com/s/HAvngRjJAbakRX40GHIx7g[https...

  • SpringBoot文件分片上传

    背景 最近好几个项目在运行过程中客户都提出文件上传大小的限制能否设置的大一些,用户经常需要上传好几个G的资料文件,...

  • 分布式文件上传的思路

    1.问题描述 现在好多应用都不止一台服务器,这就给文件上传带来了麻烦。尤其是对大文件的分片上传,每个分片可能到达不...

网友评论

      本文标题:确保自然顺序分片上传文件

      本文链接:https://www.haomeiwen.com/subject/xwcfnctx.html