java 实现多线程复制功能,支持中断后继续。
CopyTask.java
package copyFileTest;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
public class CopyTask implements Callable<String> {
// 缓冲区大小
private int bufferSize = 10240;
private CountDownLatch latch;
private RandomAccessFile file = null;
private RandomAccessFile tempFile = null;
private RandomAccessFile inputFile = null;
private int id;
private long startPosition;
private long endPosition;
private long currentPosition;
public CopyTask(File file, File tmpFile, File inputFile, int id,
CountDownLatch latch, int bufferSize) {
try {
this.file = new RandomAccessFile(file, "rw");
this.tempFile = new RandomAccessFile(tmpFile, "rw");
this.inputFile = new RandomAccessFile(inputFile, "r");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
this.id = id;
this.latch = latch;
this.bufferSize = bufferSize;
}
public String call() throws Exception {
try {
tempFile.seek((id - 1) * 28);
tempFile.readInt();
this.startPosition = tempFile.readLong();
this.endPosition = tempFile.readLong();
this.currentPosition = tempFile.readLong();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Thread " + id + " begin!");
while (true) {
try {
tempFile.seek(id * 28 - 8);
if (currentPosition < endPosition) {
inputFile.seek(currentPosition);
file.seek(currentPosition);
int len = 0;
byte[] b = new byte[bufferSize];
while ((len = inputFile.read(b)) != -1) {
file.write(b, 0, len);
currentPosition += len;
tempFile.seek(id * 28 - 8);
tempFile.writeLong(currentPosition);
if (currentPosition > endPosition) {
break;
}
}
System.out.println("Thread " + id + " startPosition="
+ startPosition + ",endPosition=" + endPosition
+ ",currentPosition=" + currentPosition);
}
System.out.println("Thread " + id + " finished.");
break;
} catch (IOException e) {
e.printStackTrace();
} finally {
file.close();
tempFile.close();
inputFile.close();
}
}
latch.countDown();
return "finish";
}
}
CopyFileTest.java
package copyFileTest;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CopyFileTest {
// 线程数
private int poolSize = 10;
// 每个线程的缓冲区大小
public int bufferSize = 10240;
private int loopSize = 10000; // 每个线程循环读的次数
/**
* 复制文件
*
* @param fileSource
* 要复制的文件
* @param fileTarget
* 要复制到的文件路径
*/
public void copy(String fileSource, String fileTarget) {
long startTime = System.currentTimeMillis();
File file = null;
File tempFile = null;
File targetFile = null;
CountDownLatch latch;
ExecutorService pool = Executors.newCachedThreadPool();
long contentLength = 0;
long threadLength = 0;
try {
new File(fileTarget).mkdirs();
file = new File(fileSource);
targetFile = new File(fileTarget + File.separator + file.getName());
tempFile = new File(fileTarget + File.separator + "_temp");
// 得到content的长度
contentLength = file.length();
poolSize = this.getPoolSize(contentLength);
System.out.println("total length=" + contentLength
+ " use ThreadSize:" + poolSize);
threadLength = loopSize * bufferSize;
if (file.exists() && tempFile.exists()) {
// 如果文件已存在,根据临时文件中记载的线程数量,继续上次的任务
int tmpFileLength = (int) tempFile.length() / 28 + 1;
latch = new CountDownLatch(tmpFileLength);
for (int i = 1; i < tmpFileLength; i++) {
pool.submit(new CopyTask(targetFile, tempFile, file, i,
latch, bufferSize));
}
} else {
// 如果下载的目标文件不存在,则创建新文件
latch = new CountDownLatch(poolSize);
targetFile.createNewFile();
tempFile.createNewFile();
DataOutputStream os = new DataOutputStream(
new FileOutputStream(tempFile));
for (int i = 0; i < this.poolSize; i++) {
os.writeInt(i + 1);
os.writeLong(i * threadLength);
if (i == this.poolSize - 1) {// 最后一个线程的结束位置应为文件末端
os.writeLong(contentLength);
} else {
os.writeLong((i + 1) * threadLength);
}
os.writeLong(i * threadLength);
pool.submit(new CopyTask(targetFile, tempFile, file, i + 1,
latch, bufferSize));
}
os.close();
}
// 等待下载任务完成
latch.await();
// 删除临时文件
System.out.println("删除临时文件" + tempFile.delete());
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
pool.shutdown();
System.out.println("完成复制,所用时:"
+ (System.currentTimeMillis() - startTime));
}
}
/**
* 根据总大小 缓存区与每个线程默认循环次数,判断用几个线程
*
* @param contentLength
* @return
*
*/
public int getPoolSize(long contentLength) {
int poolSize = 1;
BigDecimal contentBig = new BigDecimal(contentLength);
BigDecimal bufferBig = new BigDecimal(bufferSize);
BigDecimal loopBig = new BigDecimal(loopSize);
poolSize = contentBig.divide(bufferBig.multiply(loopBig), 0,
BigDecimal.ROUND_HALF_UP).intValue();
return poolSize;
}
public static void main(String[] args) {
String fileSource = "D:\\add.rar"; // 要复制的文件
String fileTarget = "D:\\copyTest";
new CopyFileTest().copy(fileSource, fileTarget);
}
}
分享到:
相关推荐
java多线程复制文件
8*8的国际象棋上有八个皇后他们不能在同一行。同一列和斜对角和java中用多线程复制文件
Java 单线程复制文件和使用RandomAccessFile多线程复制文件的比较,对应博客地址为http://blog.csdn.net/zmichealchow/article/details/38687431
java多线程复制文件的实例代码,需要的朋友可以参考一下
Java多线程网络爬虫(时光网为例)源码,为maven创建,有不明白请看我的博客介绍;转载请用连接注明出处。近期有人,将本人博客直接复制上传到百度文科等平台,不尊重个人努力成果。
Java实现多线的文件复制(界面)。 可以选择复制文件的路径,和复制到某处的路径。可以选择线程数量。
多线程 复制文件 冒泡排序 群聊
简单明了的java多线程使用实例,需要的朋友可以下载查看,切勿直接复制使用,理解为佳。
多线程对文件读写操作(java),提高对文件读写效率。
【IT十八掌徐培成】Java基础第17天-04.多线程复制-1avi.zip
【IT十八掌徐培成】Java基础第17天-05.多线程复制-多条跟踪.zip
【IT十八掌徐培成】Java基础第16天-02.文件多线程复制.zip
java File类字节流(复制、删除、剪切,下载)操作,多线程(用对象实现生产者消费者的例子)
java多线程tcp socket server源码@Netty 笔记 1. 内蒂 网络应用框架 特征 设计 支持多种传输类型 事件模型 高度可定制的线程模型 表现 高吞吐量,低延迟 更少的资源消耗 最小化内存拷贝 安全SSL/TLS 支持 建筑学 核 ...
经常会遇到下述问题:很多io busy的应用采取多线程的方式来解决,但这时候会发现python命令行不响应ctrl-c 了,而对应的java代码则没有问题: 复制代码 代码如下: public class Test { public static void main...
关于java的IO流基础的练习,适合刚接触IO流,没有基础的同学
12 JAVA多线程 13 JAVA网络通信 14 JAVA类加载器CLASSLOADER 15 JAVA简单工厂模式 16 JAVA中的注解 17 JAVA 图形界面 18 JAVA多线程 19 JAVA 反射机制 20 JAVA克隆CLONE(复制) 21 JAVA 网络编程 22 JAVA...
功能还算完善,支持文件打开与保存、复制粘贴删除剪切、查找替换字体选择等。
4. JAVA 多线程并发 5. JAVA 基础 5.1JAVA 异常分类及处理 5.2JAVA 反射 5.3JAVA 注解 5.4JAVA 内部类 5.5JAVA 泛型 5.6JAVA 序列化(创建可复用的 Java 对象) 5.7JAVA 复制 6. Spring 原理
使用时将db-example.setting复制于${classpath}/config/db.setting,按照配置文件中的说明替换相应值 如果使用Druid,则需参考druid-example.setting创建${classpath}/config/druid.setting文件,详情请参考官方文档...