java多线程复制文件

方法一、由n个线程完成一个文件的复制,即每个线程负责文件长度/n的一部分
这里写图片描述
若文件长度为len,由n个线程完成
线程1–读写从0到len/n
线程2–读写从2(len/n)-len/n
…..
最后一个线程–读写从len-(n-1)(len/n)


以下为代码实现部分:
一、利用RadomAccessFile作为输出流

public class MyThread implements Runnable {
    // 读取文件的起始位置
    private int start, end;
    // 源文件路径和目标文件路径
    private String scr, des;

    // 利用构造方法传入初始值
    public MyThread(int start, int end, String scr, String des) {
        super();
        this.start = start;
        this.end = end;
        this.scr = scr;
        this.des = des;
    }

    @Override
    public void run() {
        File f1 = new File(scr);
        File f2 = new File(des);
        try {
            InputStream input = new FileInputStream(f1);
            // 由于RandomAccessFile通过seek()方法可以指定输出的位置,因此选择它作为输出流

            RandomAccessFile out = new RandomAccessFile(f2,"rw");
            // 线程跳过的数据
            int t = (int)input.skip(start);
            //输出的位置
            out.seek(start);
            // 读取每一段文件的数据
            int count = 0;
            while (count++ <= (end - t)) {
                int a = (byte)input.read();
                out.write(a);
            }
            input.close();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

}

//主函数

public class Main {

    public static void main(String[] args) {

        // 源文件路径
        String scr = "/Users/wangjue/Documents/java实战入门.pdf";
        // 目标文件路径
        String des = "/Users/wangjue/Documents/java实战入门(1).pdf";
        File f = new File(scr);
        long len = f.length();// 获取文件长度
        // 假设将文件交个3个进程处理
        int count = 3;
        int num = (int) len / count;
        // 创建并启动前两个线程
        for (int i = 0; i < count - 1; i++) {
            new Thread(new MyThread(num * i, num * (i + 1), scr, des)).start();
        }
        // 创建并启动最后一个线程
        new Thread(new MyThread(2 * num, (int) len, scr, des)).start();
        long t2 = System.currentTimeMillis();


    }

}

二、输出流输出入流都选择RandomAccessFile,使用文件通道,即FileChannel进行处理时,一定要注意同步问题。
在jdk对于FileChannle有以下解释:
对于涉及通道位置或者可以更改其文件大小的操作,在任意给定时间只能进行一个这样的操作;如果尝试在第一个操作仍在进行时发起第二个操作,则会导致在第一个操作完成之前阻塞第二个操作。

以下为代码实现:

public class CopyThread implements Runnable {
    private String srcPath;
    private String destPath;
    private int start, end;

    public CopyThread(String srcPath, String destPath, int start, int end) {
        super();
        this.srcPath = srcPath;
        this.destPath = destPath;
        this.start = start;
        this.end = end;
    }

    @Override
    public void run() {
        try {
            RandomAccessFile in = new RandomAccessFile(srcPath, "r");
            RandomAccessFile out = new RandomAccessFile(destPath, "rw");
            // 将输入跳转到指定位置
            in.seek(start);
            // 从指定位置开始写
            out.seek(start);
            // 获取文件管道
            FileChannel fin = in.getChannel();
            FileChannel fout = out.getChannel();
            //对输出流锁定
            FileLock lock = fout.lock(start, end-start, false);
            // 将通道的文件传输到给定的可写入字节通道
            fin.transferTo(start, end - start, fout);
            //释放锁
            lock.release();
            in.close();
            out.close();
            } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

//主函数

package 多线程复制文件;

import java.io.File;

public class Main {

    public static void main(String[] args) {
        String srcPath = "/Users/wangjue/documents/Java实战入门.pdf";
        String destPath = "/Users/wangjue/documents/Java实战入门(1).pdf";
        //获得源文件长度
        File f = new File(srcPath);
        long len = f.length();

        int count = 3;//需要的线程数
         int oneNum = (int)len/count;

         for(int i=0;i<count-1;i++) {
             CopyThread ct = new CopyThread(srcPath, destPath, oneNum*i, oneNum*(i+1));
             new Thread(ct).start();
         }
         CopyThread ct2 = new CopyThread(srcPath, destPath, oneNum*2, (int)len);
         new Thread(ct2).start();

    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值