java多线程复制文件
人生能有几次搏?莫到白发还未博。
多线程复制文件
在日常生活中,我们要复制很多文件,这些文件特别大,于是呢,现有的复制速度满足不了我们人类的需求,我们的需求是什么?一个字——快。
所以呢,就想办法。看有没有一种速度能够让我们快速的复制文件来提高我们的效率,而恰巧,刚学完Java的IO流,就想着能不能用,于是我们用IO流通过高效率的一次读取一个数组[1024*8]的大小来读取写入文件。
但是呢,我们很贪心,就又学了线程,呀!线程是个好东西。一下子并行的速度来处理事务。于是,就想到了,咦?我是不是可以开一大堆的线程来复制我的文件呢???理论上貌似可以啊,迫不及待,于是呢,就又了今天的这一篇博客。
那么,接下来就装逼开始,各位看官,请退后!!!
嘻嘻,在学多线程复制文件之前,先来个一个线程复制文件,热热身,熟悉熟悉线程的基本语法吧。
一个线程复制文件
首先定义一个我们自己的线程类,来将复制的那一大坨代码,放入重写的run()方法中。
public class MyThread extends Thread {
@Override
public void run() {
String scrFile="CopyFile.java";//目标文件
String aimFile="CopyFile1.java";//目的文件
FileInputStream InputStream=null;
FileOutputStream outputStream=null;
try {
InputStream = new FileInputStream(scrFile);//读入IO流
outputStream = new FileOutputStream(aimFile);//输出IO流
int len=0;
byte[] bytes = new byte[1024];//每次读取1024字节复制
while ((len = InputStream.read(bytes)) !=-1){
outputStream.write(bytes,0,len);
outputStream.flush();//字符流刷新
}
} catch (FileNotFoundException e) {
System.out.println(e);
} catch (IOException e) {
System.out.println(e);
}finally {
if(InputStream!=null){
try {
InputStream.close();//关闭IO流
outputStream.close();
} catch (IOException e) {
System.out.println(e);
}
}
}
}
}
然后就开启线程吧。
public class Teset {
public static void main(String[] args) {
MyThread th1 = new MyThread();
th1.start();
}
}
一个线程的复制文件练手完毕,就开始我们的多线程复制文件。
首先,我们对整个框架进行分析。
假如 文件大小是3G,我们开启三个线程。那么就是每个线程复制一个G,假如有剩余的字节没有被复制,我们额外开启一个线程去复制。那么最重要的问题就是,如何将三个线程要复制的具体字节捕获。记得我们学过一个类,RandomAccessFile类中有个seek()方法可以定位字节数,相当于一个简单的指针吧。那么我们就将每个线程的开始位置和结束位置获得,下一个线程开启的位置就是上一个线程结束的位置,这样,就可以有序的将文件复制完成。具体的我们看代码吧,每一行都有注释。
为了能够直观,就将Thread类也放在一块。
package org.xupt.Demo9;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class CopyFile {
public static void main(String[] args) throws FileNotFoundException {
File file = new File("CopyFile.java");//封装文件,获得操作对象
long length = file.length();//获得文件的总长度
long threadNum=3;//定义三个线程
long threadLength=length/threadNum;//平均每个线程要复制的字节
for (int i = 0; i <threadLength ; i++) {
long start=threadLength*i; //每个线程的开始位置
long end=threadLength*(i+1); //每个线程的结束位置
new CopyThread(start,end,"CopyFile.java","CopyFile1111111111.java").start();
}
//剩余字节怎么办?
//假如我们的总字节数,不够被我们预先设定的线程数均分
//那么就在补一个线程,把剩余的字节数,再补上
long y=length%threadNum;
if(y!=0){
long start=threadNum*threadLength;
long end=threadNum*threadLength+y;
new CopyThread(start,end,"CopyFile.java","CopyFile1111111111.java").start();
}
}
static class CopyThread extends Thread{
long start;
long end;
RandomAccessFile scr;
RandomAccessFile aim;
public CopyThread(long start, long end, String scr, String aim) throws FileNotFoundException {
this.start = start;
this.end = end;
this.scr = new RandomAccessFile(scr,"rw");
this.aim = new RandomAccessFile(aim,"rw");
}
@Override
public void run() {
try {
//定义指针位置
scr.seek(start);
aim.seek(start);
//频繁的读写操作
byte[] bytes = new byte[10];
int len = 0;
while (start < end && (len = scr.read(bytes)) != -1) {
start += len;//记录字节数
System.out.println(len);
aim.write(bytes, 0, len);
}
//释放资源
scr.close();
aim.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
好,那么多线程复制文件是非常迅速的,希望大家能够受用!!!