多线程拷贝文件比较慢? 求帮忙分析

本贴最后更新于 2968 天前,其中的信息可能已经时移世异
package com.pangwen.usefultools.io; import java.io.*; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; /** * 文件拷贝工具类 * Created on 2017/4/18. * * @author pangwen * @version 0.1 */public final class FileCopyUtils { /** * 大于500M的文件为大文件 */ private static final long BIG_FILE_SIZE = 1024 * 1024 * 500; /** * byte[]默认长度为1024 */ private static final int BUFFER_SIZE = 1024; /** * 最大线程数 */ private static final int MAX_THREAD_NUM = 5; /** * 静态内部类实现多线程 */ private static class FileCopyWorker implements Runnable { private final File srcFile; private final File targetFile; private final long startPosition; private final long endPosition; /** * constructor * * @param srcFile 源文件 * @param targetFile 目标文件 * @param startPosition 文件开始位置 * @param endPosition 文件结束位置 */ public FileCopyWorker(final File srcFile, final File targetFile, final long startPosition, final long endPosition) { this.srcFile = srcFile; this.targetFile = targetFile; this.startPosition = startPosition; this.endPosition = endPosition; } //@Override public void run() { RandomAccessFile rin = null; RandomAccessFile rout = null; try { rin = new RandomAccessFile(srcFile, "r"); rin.seek(startPosition); rout = new RandomAccessFile(targetFile, "rw"); rout.seek(startPosition); byte[] buffer = new byte[BUFFER_SIZE]; int i; int readLength = 0; while ((i = rin.read(buffer)) != -1 && startPosition + readLength <= endPosition) { rout.write(buffer, 0, i); readLength += i; } } catch (IOException e) { e.printStackTrace(); } finally { try { if (null != rin) rin.close(); } catch (Exception e) { e.printStackTrace(); } try { if (null != rout) rout.close(); } catch (Exception e) { e.printStackTrace(); } } } } /** * nio拷贝文件 * * @param srcFile 源文件 * @param targetFile 目标文件 */ public static void copyFileNio(final File srcFile, final File targetFile) throws FileNotFoundException { if (null == srcFile) throw new FileNotFoundException("src file not found!"); makeParentDirs(targetFile); FileInputStream in = new FileInputStream(srcFile); FileOutputStream out = new FileOutputStream(targetFile); //获取通道 FileChannel inChannel = null; FileChannel outChannel = null; try { inChannel = in.getChannel(); outChannel = out.getChannel(); //创建缓冲区 ByteBuffer buffer = ByteBuffer.allocate(1024); //将数据读入缓冲区 while (inChannel.read(buffer) != -1) { //flip() 方法让缓冲区可以将新读入的数据写入另一个通道。 buffer.flip(); //将缓冲区数据写入文件 outChannel.write(buffer); //clear() 方法重设缓冲区,使它可以接受读入的数据。 buffer.clear(); } } catch (IOException e) { e.printStackTrace(); } finally { if (inChannel != null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } if (outChannel != null) { try { outChannel.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 拷贝文件 * * @param srcFile 源文件 * @param targetFile 目标文件 * @param allowMultipleThread 是否开启多线程 * @throws FileNotFoundException */ public static void copyFile(final File srcFile, final File targetFile, final boolean allowMultipleThread) throws FileNotFoundException { if (null == srcFile) throw new FileNotFoundException("src file not found!"); //创建父文件夹 makeParentDirs(targetFile); long srcFileLength = srcFile.length(); if (allowMultipleThread && srcFileLength > BIG_FILE_SIZE) { try { //大文件调用多线程 copyFileMultipleThread(srcFile, targetFile); return; } catch (Exception e) { e.printStackTrace(); //多线程拷贝文件失败时调用单线程拷贝文件 copyFile(srcFile, targetFile, false); } } FileInputStream in = null; FileOutputStream out = null; try { in = new FileInputStream(srcFile); out = new FileOutputStream(targetFile); byte[] buffer = new byte[BUFFER_SIZE]; int i; while ((i = in.read(buffer)) != -1) { out.write(buffer, 0, i); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (null != in) in.close(); } catch (Exception e) { e.printStackTrace(); } try { if (null != out) out.close(); } catch (Exception e) { e.printStackTrace(); } } } /** * 多线程拷贝文件 RandomAccessFile * * @param srcFile 源文件 * @param targetFile 目标文件 */ private static void copyFileMultipleThread(final File srcFile, final File targetFile) { final long srcFileLength = srcFile.length(); int threadNum = (int) (srcFileLength / BIG_FILE_SIZE); if (threadNum > MAX_THREAD_NUM) threadNum = MAX_THREAD_NUM; long residuumFileLength = srcFileLength % threadNum; //每份文件大小 long perFileSize = (srcFileLength - residuumFileLength) / threadNum; //开始位置 long startPosition = 0; //结束位置 long endPosition = perFileSize; for (int i = 0; i < threadNum; i++) { new Thread(new FileCopyWorker(srcFile, targetFile, startPosition, endPosition)).start(); //下一现场读取文件开始位置 startPosition = endPosition + 1; //下一现场读取文件结束位置 endPosition += perFileSize; //最后一个线程读取到文件末 if (i == threadNum - 2) endPosition = srcFileLength; } } private static void makeParentDirs(final File file) throws FileNotFoundException { if (null == file) throw new FileNotFoundException("target file must not be null!"); File parent = file.getParentFile(); if (!parent.exists()) parent.mkdirs(); } private FileCopyUtils() { throw new IllegalAccessError("can not create instance!"); } }
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3201 引用 • 8216 回帖 • 1 关注
  • IO
    8 引用 • 20 回帖
  • Test

    如果你要试验论坛功能,请到 Sandbox 标签下发帖。

    14 引用 • 29 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • Gitea

    Gitea 是一个开源社区驱动的轻量级代码托管解决方案,后端采用 Go 编写,采用 MIT 许可证。

    5 引用 • 16 回帖 • 2 关注
  • Thymeleaf

    Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎。类似 Velocity、 FreeMarker 等,它也可以轻易的与 Spring 等 Web 框架进行集成作为 Web 应用的模板引擎。与其它模板引擎相比,Thymeleaf 最大的特点是能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个 Web 应用。

    11 引用 • 19 回帖 • 395 关注
  • Ngui

    Ngui 是一个 GUI 的排版显示引擎和跨平台的 GUI 应用程序开发框架,基于
    Node.js / OpenGL。目标是在此基础上开发 GUI 应用程序可拥有开发 WEB 应用般简单与速度同时兼顾 Native 应用程序的性能与体验。

    7 引用 • 9 回帖 • 402 关注
  • 一些有用的避坑指南。

    69 引用 • 93 回帖
  • Hprose

    Hprose 是一款先进的轻量级、跨语言、跨平台、无侵入式、高性能动态远程对象调用引擎库。它不仅简单易用,而且功能强大。你无需专门学习,只需看上几眼,就能用它轻松构建分布式应用系统。

    9 引用 • 17 回帖 • 645 关注
  • jsoup

    jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。

    6 引用 • 1 回帖 • 490 关注
  • Typecho

    Typecho 是一款博客程序,它在 GPLv2 许可证下发行,基于 PHP 构建,可以运行在各种平台上,支持多种数据库(MySQL、PostgreSQL、SQLite)。

    12 引用 • 67 回帖 • 445 关注
  • 周末

    星期六到星期天晚,实行五天工作制后,指每周的最后两天。再过几年可能就是三天了。

    14 引用 • 297 回帖
  • 30Seconds

    📙 前端知识精选集,包含 HTML、CSS、JavaScript、React、Node、安全等方面,每天仅需 30 秒。

    • 精选常见面试题,帮助您准备下一次面试
    • 精选常见交互,帮助您拥有简洁酷炫的站点
    • 精选有用的 React 片段,帮助你获取最佳实践
    • 精选常见代码集,帮助您提高打码效率
    • 整理前端界的最新资讯,邀您一同探索新世界
    488 引用 • 384 回帖 • 8 关注
  • 浅吟主题

    Jeffrey Chen 制作的思源笔记主题,项目仓库:https://github.com/TCOTC/Whisper

    1 引用 • 28 回帖
  • OneDrive
    2 引用 • 2 关注
  • OpenShift

    红帽提供的 PaaS 云,支持多种编程语言,为开发人员提供了更为灵活的框架、存储选择。

    14 引用 • 20 回帖 • 662 关注
  • Android

    Android 是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    336 引用 • 324 回帖
  • 音乐

    你听到信仰的声音了么?

    62 引用 • 512 回帖
  • BookxNote

    BookxNote 是一款全新的电子书学习工具,助力您的学习与思考,让您的大脑更高效的记忆。

    笔记整理交给我,一心只读圣贤书。

    1 引用 • 1 回帖
  • 面试

    面试造航母,上班拧螺丝。多面试,少加班。

    326 引用 • 1395 回帖
  • 自由行
  • 运维

    互联网运维工作,以服务为中心,以稳定、安全、高效为三个基本点,确保公司的互联网业务能够 7×24 小时为用户提供高质量的服务。

    151 引用 • 257 回帖
  • Netty

    Netty 是一个基于 NIO 的客户端-服务器编程框架,使用 Netty 可以让你快速、简单地开发出一个可维护、高性能的网络应用,例如实现了某种协议的客户、服务端应用。

    49 引用 • 33 回帖 • 35 关注
  • 创造

    你创造的作品可能会帮助到很多人,如果是开源项目的话就更赞了!

    186 引用 • 1020 回帖
  • gRpc
    11 引用 • 9 回帖 • 99 关注
  • 微服务

    微服务架构是一种架构模式,它提倡将单一应用划分成一组小的服务。服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在独立的进程中。服务于服务之间才用轻量级的通信机制互相沟通。每个服务都围绕着具体业务构建,能够被独立的部署。

    96 引用 • 155 回帖
  • HBase

    HBase 是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的 Google 论文 “Bigtable:一个结构化数据的分布式存储系统”。就像 Bigtable 利用了 Google 文件系统所提供的分布式数据存储一样,HBase 在 Hadoop 之上提供了类似于 Bigtable 的能力。

    17 引用 • 6 回帖 • 67 关注
  • TensorFlow

    TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

    20 引用 • 19 回帖
  • CloudFoundry

    Cloud Foundry 是 VMware 推出的业界第一个开源 PaaS 云平台,它支持多种框架、语言、运行时环境、云平台及应用服务,使开发人员能够在几秒钟内进行应用程序的部署和扩展,无需担心任何基础架构的问题。

    5 引用 • 18 回帖 • 187 关注
  • OkHttp

    OkHttp 是一款 HTTP & HTTP/2 客户端库,专为 Android 和 Java 应用打造。

    16 引用 • 6 回帖 • 93 关注
  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    201 引用 • 120 回帖