java多線程復制文件
package com.test;import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile;
public class FileCoper { private static final String _ORIGIN_FILE_MODE = "r";
private static final String _TARGET_FILE_MODE = "rw"; private static long time1 = 0l; private String originFileName; private String targetFileName; private RandomAccessFile originFile; private RandomAccessFile targetFile; private int threadCount; private static int totalThreadCount = 0; private static int executedCount = 0; public FileCoper() { this.threadCount = 1; totalThreadCount = this.threadCount; } public FileCoper(String originFile, String targetFile) { try { this.originFileName = originFile; this.targetFileName = targetFile; this.originFile = new RandomAccessFile((originFile), FileCoper._ORIGIN_FILE_MODE); this.targetFile = new RandomAccessFile((targetFile), FileCoper._TARGET_FILE_MODE); this.threadCount = 1; totalThreadCount = this.threadCount; } catch (FileNotFoundException e) { e.printStackTrace(); } } public FileCoper(String originFile, String targetFile, int threadCount) { try { this.originFileName = originFile; this.targetFileName = targetFile; this.originFile = new RandomAccessFile((originFile), FileCoper._ORIGIN_FILE_MODE); this.targetFile = new RandomAccessFile((targetFile), FileCoper._TARGET_FILE_MODE); this.threadCount = 1; totalThreadCount = this.threadCount; } catch (FileNotFoundException e) { e.printStackTrace(); } } public void init(String originFile, String targetFile) throws Exception { this.originFileName = originFile; this.targetFileName = targetFile; this.originFile = new RandomAccessFile((originFile), FileCoper._ORIGIN_FILE_MODE); this.targetFile = new RandomAccessFile((targetFile), FileCoper._TARGET_FILE_MODE); this.threadCount = 1; totalThreadCount = this.threadCount; } public void init(String originFile, String targetFile, int threadCount) throws Exception { this.originFileName = originFile; this.targetFileName = targetFile; this.originFile = new RandomAccessFile((originFile), FileCoper._ORIGIN_FILE_MODE); this.targetFile = new RandomAccessFile((targetFile), FileCoper._TARGET_FILE_MODE); this.threadCount = threadCount; totalThreadCount = this.threadCount; } public void init(RandomAccessFile originFile, RandomAccessFile targetFile) throws Exception { this.originFile = originFile; this.targetFile = targetFile; this.threadCount = 1; totalThreadCount = this.threadCount; } public void init(RandomAccessFile originFile, RandomAccessFile targetFile, int threadCount) throws Exception { this.originFile = originFile; this.targetFile = targetFile; this.threadCount = threadCount; totalThreadCount = this.threadCount; } public static synchronized void finish() { FileCoper.executedCount ++; System.out.println("總線程【" + FileCoper.totalThreadCount + "】,已經完成【" + FileCoper.executedCount + "】個線程的復制!!!"); if (FileCoper.totalThreadCount == FileCoper.executedCount){ long time2 = System.currentTimeMillis(); System.out.println("花費時長:"+(time2-time1)); System.out.println("所有【" + FileCoper.totalThreadCount + "】線程復制完成!!!"); } } public void start() throws Exception { if (this.originFile.length() == 0) return; if (this.threadCount == 0) this.threadCount = 1; // 設置目標文件大小 this.targetFile.setLength(this.originFile.length()); this.targetFile.seek(0); this.originFile.seek(0); time1 = System.currentTimeMillis(); System.out.println(this.originFile.length()); // 把文件分塊,每一塊有一對值:當前塊在文件中的起始位置和結束位置 long[][] splits = new long[this.threadCount][2]; long originFileLength = this.originFile.length(); int startPos = 0; for (int i = 0; i < this.threadCount; i++) { splits[i][0] = 0; splits[i][1] = 0; if (i == 0) { splits[i][0] = 0; splits[i][1] = originFileLength / this.threadCount; } else if (i == this.threadCount - 1) { // 注意:此處不能加1,如果加1,線程多文件就會出現亂碼 // splits[i][0] = startPos + 1; splits[i][0] = startPos; splits[i][1] = originFileLength; } else { // 注意:此處不能加1,如果加1,線程多文件就會出現亂碼 // splits[i][0] = startPos + 1; splits[i][0] = startPos; splits[i][1] = startPos + originFileLength / this.threadCount; } startPos += originFileLength / this.threadCount; // System.out.println(splits[i][0] + " " + splits[i][1]); Coper fc = new Coper("thread-" + i); fc.init(this.originFile, this.targetFile, splits[i][0], splits[i][1]); fc.setOriginFileName(this.originFileName); fc.setTargetFileName(this.targetFileName); fc.start(); } } public void startNew() throws Exception { if (this.originFile.length() == 0) return; // 設置目標文件大小 this.targetFile.setLength(this.originFile.length()); this.targetFile.seek(0); this.originFile.seek(0); long startPosition; long endPosition; long block = this.originFile.length() / 1029; if (block <= 1) this.threadCount = 1; for (int i = 0; i < this.threadCount; i++) { // 定義每次轉移的長度 startPosition = i * 1029 * (block / this.threadCount); endPosition = (i + 1) * 1029 * (block / this.threadCount); if (i == (this.threadCount - 1)) endPosition = this.originFile.length(); Coper fc = new Coper("thread-" + i); fc.init(this.originFile, this.targetFile, startPosition, endPosition); fc.setOriginFileName(this.originFileName); fc.setTargetFileName(this.targetFileName); fc.start(); } } private class Coper extends Thread { private String originFileName; private String targetFileName; private RandomAccessFile originFile; private RandomAccessFile targetFile; private String threadId; private long startPosition; private long endPosition; private long blockCapacity; public void setOriginFileName(String originFileName) { this.originFileName = originFileName; } public void setTargetFileName(String targetFileName) { this.targetFileName = targetFileName; } public Coper(String threadId) { this.threadId = threadId; } public void init(RandomAccessFile originFile, RandomAccessFile targetFile, long startPosition, long endPosition) throws Exception { this.originFile = originFile; this.targetFile = targetFile; this.startPosition = startPosition; this.endPosition = endPosition; this.blockCapacity = this.endPosition - this.startPosition; } public void run() { // System.out.println(this.threadId + " 啟動,開始復制文件【" + // this.originFileName + "】中的文件塊【" + this.startPosition + "," + // this.endPosition + "】到目標文件【" + this.targetFileName + "】中..."); synchronized (this.originFile) { try { // 記錄當前拷貝的字節數 int copyCount = 0; // 數據拷貝的啟示偏移量 long offSet = this.startPosition; byte[] b = new byte[16 * 1024 * 1024]; // 動態設置一次讀取的字節數緩沖 long blockSize = 0; while (copyCount < this.blockCapacity) { this.originFile.seek(offSet); if (this.blockCapacity - copyCount > 16 * 1024 * 1024) blockSize = 16 * 1024 * 1024; else blockSize = this.blockCapacity - copyCount; if (blockSize > this.blockCapacity - copyCount) blockSize = this.blockCapacity - copyCount; int count = this.originFile.read(b, 0, (int) blockSize); synchronized (this.targetFile) { try { if (copyCount == 0) this.targetFile.seek(offSet); else this.targetFile.seek(offSet + 1); this.targetFile.write(b, 0, count); } catch (IOException e) { e.printStackTrace(); } } // 增加拷貝的字節數 copyCount += count; // 拷貝其實【偏移量下移 offSet += count; } } catch (IOException e) { e.printStackTrace(); } } // System.out.println(this.threadId + " 復制文件【" + this.originFileName // + "】中的文件塊【" + this.startPosition + "," + this.endPosition + // "】到目標文件【" + this.targetFileName + "】完成!"); // 通知主線程,當前線程完成復制工作 FileCoper.finish(); } } public static void main(String[] args) throws Exception { FileCoper fc = new FileCoper(); fc.init("e:/InitialData_zhihuan.sql", "e:/InitialData_zhihuan2.sql", 30); //fc.init("d:/ValueAdd_11.txt", "d:/ValueAdd_111.txt", 100); // fc.init("D:\tools\music\做你的愛人.mp3", "d:/做你的愛人_5.mp3", 10); //fc.init("E:\電影\最黑暗侵襲.rmvb", "d:/最黑暗侵襲_1.rmvb", 100); /* // 讀入鍵盤輸入 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 文件來源 String originFile; // 文件目標 String targetFile; System.out.println("【源文件、目標文件、線程數】"); System.out.print("要復制的源文件:"); originFile = br.readLine(); System.out.print("文件復制到目標文件:"); targetFile = br.readLine(); System.out.print("切分線程數:"); int threadCount = Integer.parseInt(br.readLine()); fc.init(originFile, targetFile, threadCount);*/ // fc.startNew(); long time1 = System.currentTimeMillis(); fc.start(); long time2 = System.currentTimeMillis(); System.out.println(time2-time1); }
}</pre>
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!