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

本贴最后更新于 2531 天前,其中的信息可能已经时移世异
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 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3165 引用 • 8206 回帖
  • IO
    8 引用 • 20 回帖
  • Test

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

    14 引用 • 29 回帖 • 1 关注

相关帖子

欢迎来到这里!

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

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

    表达能力实在捉鸡。。 然后 markdown 不会用,代码贴的很凌乱。

    1 回复
  • 其他回帖
  • 88250

    估计是,你得介绍下思路啊

    1 回复
  • zhongmc

    不错

    1 回复
  • shinchan

    看了代码,应该不存在资源竞争的问题,难道是 RandomAccessFile 并发的问题?

    1 回复
  • 查看全部回帖

推荐标签 标签

  • 以太坊

    以太坊(Ethereum)并不是一个机构,而是一款能够在区块链上实现智能合约、开源的底层系统。以太坊是一个平台和一种编程语言 Solidity,使开发人员能够建立和发布下一代去中心化应用。 以太坊可以用来编程、分散、担保和交易任何事物:投票、域名、金融交易所、众筹、公司管理、合同和知识产权等等。

    34 引用 • 367 回帖 • 2 关注
  • H2

    H2 是一个开源的嵌入式数据库引擎,采用 Java 语言编写,不受平台的限制,同时 H2 提供了一个十分方便的 web 控制台用于操作和管理数据库内容。H2 还提供兼容模式,可以兼容一些主流的数据库,因此采用 H2 作为开发期的数据库非常方便。

    11 引用 • 54 回帖 • 638 关注
  • Kotlin

    Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,由 JetBrains 设计开发并开源。Kotlin 可以编译成 Java 字节码,也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。在 Google I/O 2017 中,Google 宣布 Kotlin 成为 Android 官方开发语言。

    19 引用 • 33 回帖 • 21 关注
  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    534 引用 • 671 回帖
  • Webswing

    Webswing 是一个能将任何 Swing 应用通过纯 HTML5 运行在浏览器中的 Web 服务器,详细介绍请看 将 Java Swing 应用变成 Web 应用

    1 引用 • 15 回帖 • 635 关注
  • NGINX

    NGINX 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 NGINX 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本 0.1.0 发布于 2004 年 10 月 4 日。

    311 引用 • 546 回帖 • 56 关注
  • HBase

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

    17 引用 • 6 回帖 • 32 关注
  • WordPress

    WordPress 是一个使用 PHP 语言开发的博客平台,用户可以在支持 PHP 和 MySQL 数据库的服务器上架设自己的博客。也可以把 WordPress 当作一个内容管理系统(CMS)来使用。WordPress 是一个免费的开源项目,在 GNU 通用公共许可证(GPLv2)下授权发布。

    45 引用 • 113 回帖 • 321 关注
  • JVM

    JVM(Java Virtual Machine)Java 虚拟机是一个微型操作系统,有自己的硬件构架体系,还有相应的指令系统。能够识别 Java 独特的 .class 文件(字节码),能够将这些文件中的信息读取出来,使得 Java 程序只需要生成 Java 虚拟机上的字节码后就能在不同操作系统平台上进行运行。

    180 引用 • 120 回帖 • 2 关注
  • 心情

    心是产生任何想法的源泉,心本体会陷入到对自己本体不能理解的状态中,因为心能产生任何想法,不能分出对错,不能分出自己。

    59 引用 • 369 回帖
  • Quicker

    Quicker 您的指尖工具箱!操作更少,收获更多!

    16 引用 • 68 回帖
  • 架构

    我们平时所说的“架构”主要是指软件架构,这是有关软件整体结构与组件的抽象描述,用于指导软件系统各个方面的设计。另外还有“业务架构”、“网络架构”、“硬件架构”等细分领域。

    139 引用 • 441 回帖
  • Hprose

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

    9 引用 • 17 回帖 • 591 关注
  • RIP

    愿逝者安息!

    8 引用 • 92 回帖 • 285 关注
  • 招聘

    哪里都缺人,哪里都不缺人。

    189 引用 • 1056 回帖
  • FlowUs

    FlowUs.息流 个人及团队的新一代生产力工具。

    让复杂的信息管理更轻松、自由、充满创意。

    1 引用 • 3 关注
  • Rust

    Rust 是一门赋予每个人构建可靠且高效软件能力的语言。Rust 由 Mozilla 开发,最早发布于 2014 年 9 月。

    57 引用 • 22 回帖
  • 数据库

    据说 99% 的性能瓶颈都在数据库。

    330 引用 • 614 回帖
  • Love2D

    Love2D 是一个开源的, 跨平台的 2D 游戏引擎。使用纯 Lua 脚本来进行游戏开发。目前支持的平台有 Windows, Mac OS X, Linux, Android 和 iOS。

    14 引用 • 53 回帖 • 506 关注
  • Electron

    Electron 基于 Chromium 和 Node.js,让你可以使用 HTML、CSS 和 JavaScript 构建应用。它是一个由 GitHub 及众多贡献者组成的活跃社区共同维护的开源项目,兼容 Mac、Windows 和 Linux,它构建的应用可在这三个操作系统上面运行。

    15 引用 • 136 回帖
  • CSDN

    CSDN (Chinese Software Developer Network) 创立于 1999 年,是中国的 IT 社区和服务平台,为中国的软件开发者和 IT 从业者提供知识传播、职业发展、软件开发等全生命周期服务,满足他们在职业发展中学习及共享知识和信息、建立职业发展社交圈、通过软件开发实现技术商业化等刚性需求。

    14 引用 • 155 回帖
  • 运维

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

    148 引用 • 257 回帖 • 1 关注
  • JetBrains

    JetBrains 是一家捷克的软件开发公司,该公司位于捷克的布拉格,并在俄国的圣彼得堡及美国麻州波士顿都设有办公室,该公司最为人所熟知的产品是 Java 编程语言开发撰写时所用的集成开发环境:IntelliJ IDEA

    18 引用 • 54 回帖
  • IDEA

    IDEA 全称 IntelliJ IDEA,是一款 Java 语言开发的集成环境,在业界被公认为最好的 Java 开发工具之一。IDEA 是 JetBrains 公司的产品,这家公司总部位于捷克共和国的首都布拉格,开发人员以严谨著称的东欧程序员为主。

    180 引用 • 400 回帖
  • GitBook

    GitBook 使您的团队可以轻松编写和维护高质量的文档。 分享知识,提高团队的工作效率,让用户满意。

    3 引用 • 8 回帖 • 1 关注
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 429 关注
  • CodeMirror
    1 引用 • 2 回帖 • 109 关注