用多线程实现文件复制:
main函数类:
1 public class ThreadCopyFile { 2 3 public static void main(String[] args) { 4 // TODO Auto-generated method stub 5 copyFile(); 6 } 7 8 static void copyFile() { 9 // 源文件 10 File file = new File("E:\test\ai.mp4"); 11 // 目标文件 12 File file2 = new File("E:\test\copyai.mp4"); 13 // 文件总大小,以字节为单位 14 long fileSize = file.length(); 15 // 分的块数,进程数 16 int blockCount = 3; 17 // 每块的大小 18 long perBlockSize = fileSize / blockCount; 19 // 最后一块的大小 20 long lastBlockSize = perBlockSize + fileSize % blockCount; 21 // 前两次:0,1 22 for (int i = 0; i < blockCount - 1; i++) { 23 // 传入参数依次为:源文件,目标文件,文件块起始位置,文件块大小,线程名 24 new CopyThread(file, file2, perBlockSize * i, perBlockSize, "tom" 25 + i).start(); 26 } 27 // 最后一次 28 new CopyThread(file, file2, perBlockSize * (blockCount - 1), 29 lastBlockSize, "CC").start(); 30 } 31 }
线程类:
1 public class CopyThread extends Thread { 2 private File file; 3 private long begin; 4 private File file2; 5 private long perSize; 6 7 public CopyThread() { 8 // TODO Auto-generated constructor stub 9 10 } 11 12 public CopyThread(File file, File file2, long begin, long perSize, 13 String name) { 14 super(name);// 进程名 15 this.begin = begin;// 起始位置 16 this.file = file;// 源文件 17 this.file2 = file2;// 目标文件 18 this.perSize = perSize;// 文件块大小 19 20 } 21 22 @Override 23 public void run() { 24 // 为每个线程打开一个RandomAccessFile对象, 25 // 让每个线程分别负责读取文件的不同部分 26 RandomAccessFile raf = null; 27 RandomAccessFile raf2 = null; 28 // 粒度,如果大了,会使副本文件大于源文件,如果小了,会加长复制文件的时间 29 // 复制结果相差10k,是不是应该在结尾1k1k地复制呢?或者让文件最后的余数1个字节1个字节地读,文件最后的字节余数是线程个数!! 30 // hahaha问题已解决!!! 31 byte[] b = new byte[10 * 1024]; 32 int i = 0; 33 // 记录复制到每个文件块的光标 34 int len = 0; 35 try { 36 raf = new RandomAccessFile(file, "rw"); 37 raf2 = new RandomAccessFile(file2, "rw"); 38 // 设置读文件起始点 39 raf.seek(begin); 40 // 默认文件是从后往前读的CC->tom1->tom0??? 41 // 当没有读到文件的末尾并且已经读的长度小于每个线程分配的文件块的大小时,执行 42 // 如果不加(len<perSize)只是从文件结尾依次读,并且把已经读的覆盖而以 43 while (((i = raf.read(b)) != -1) && (len < perSize)) { 44 raf2.seek(begin); 45 // 精准到1字节!! 46 raf2.write(b, 0, i); 47 len += i; 48 begin += i; 49 } 50 // System.out.println(Thread.currentThread().getName()); 51 } catch (IOException e) { 52 // TODO Auto-generated catch block 53 e.printStackTrace(); 54 } finally { 55 try { 56 raf.close(); 57 raf2.close(); 58 } catch (IOException e) { 59 // TODO Auto-generated catch block 60 e.printStackTrace(); 61 } 62 } 63 } 64 }