人生能有几次搏?莫到白发还未博。

多线程复制文件

    在日常生活中,我们要复制很多文件,这些文件特别大,于是呢,现有的复制速度满足不了我们人类的需求,我们的需求是什么?一个字——快。

    所以呢,就想办法。看有没有一种速度能够让我们快速的复制文件来提高我们的效率,而恰巧,刚学完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();
            }
        }
    }
}

 好,那么多线程复制文件是非常迅速的,希望大家能够受用!!!