/** * FileName:RandomAccessFile.java * @author zhanggw * @date 2018年1月19日 下午7:42:43 */ package com.kenick.download; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.RandomAccessFile; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @ClassName RandomAccessFile * @author zhanggw * @date 2018年1月19日 下午7:42:43 */ public class ThreadPoolWriteDemo { public static int threadNum = 128; // 线程数 public static int cacheSize = 1024*1024*8; // 缓存8MB public static long startTime; // 开始时间 public static int srcFileSize; // 原文件大小 public static ExecutorService executorService = Executors.newFixedThreadPool(threadNum); public static void main(String[] args) throws Exception{ String src = "D:/temp/bingxuebao.mp4"; // 复制原文件 String dst = "F:/temp/tmp17.mp4"; // 复制目标文件 startTime = System.currentTimeMillis(); // 开始时间 // 使用多线程复制文件 copy(src, dst, threadNum); // 开启线程计算完成时间 new Thread(new Runnable() { @Override public void run() { while(true){ try { if(executorService.isTerminated()){ long endTime = System.currentTimeMillis(); int fileSize = srcFileSize/1024/1024; long spent = endTime - startTime; System.out.println("文件总大小:"+fileSize+"MB"); System.out.println("花费时间:"+spent/1000+"秒,"+spent+"毫秒"); System.out.println("线程数:"+threadNum); System.out.println("缓存大小:"+(cacheSize/1024/1024)+"MB"); if(spent/1000==0){ System.out.println("拷贝速度:"+(fileSize/spent)+"MB/毫秒"); }else{ System.out.println("拷贝速度:"+(fileSize/(spent/1000))+"MB/S"); } break; } Thread.sleep(1); // 切换CPU } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } /** * 使用threadNum个线程复制文件 */ public static void copy(String src,String dst,int threadNum){ try { // 获取原文件总大小 FileInputStream fileInputStream = new FileInputStream(src); srcFileSize = fileInputStream.available(); fileInputStream.close(); // 获取每个线程需要复制的字节大小 int partSize = srcFileSize/threadNum; // 目的文件夹如果不存在,则创建 File dstFile = new File(dst); if(!dstFile.exists()){ dstFile.createNewFile(); } // 启用threadNum个线程进行复制文件 for(int i=0;i<threadNum;i++){ int start = partSize * i; int end = (i==(threadNum-1))?srcFileSize:partSize*(i+1); executorService.execute(new Runnable() { @Override public void run() { // 将src文件的start到end部分字节复制到dstFile中 copyByteToFile(src,start,end,dstFile); } }); } // 关闭线程池,已提交的线程执行完毕后会自动结束 executorService.shutdown(); } catch (Exception e) { e.printStackTrace(); } } /** * 将原文件复制到目的文件,通过字节划分 */ @SuppressWarnings("resource") public static void copyByteToFile(String src,int start,int end,File dstFile){ try { String threadName = Thread.currentThread().getName(); // 线程名 System.out.println("线程"+threadName+"开始拷贝文件数据,拷贝数据段:"+start+"-"+end); // 定位目标文件位置 RandomAccessFile randomAccessFile = new RandomAccessFile(dstFile, "rw"); randomAccessFile.seek(start); // 定位原文件位置 InputStream inputStream = new FileInputStream(src); inputStream = skipFully(inputStream,start); // 复制文件内容 int sumSize = end - start; // 复制总字节数 int readSize = 1024*1024*8; // 缓存8MB while(sumSize>0){ // 缓存大于拷贝字节,使用拷贝字节 if(readSize>sumSize){ readSize = sumSize; } // 从原文件输入流获取拷贝字节数据 byte[] tmp = new byte[readSize]; inputStream.read(tmp); // 向目标文件写入拷贝字节数据 randomAccessFile.write(tmp); sumSize -= readSize; } // 拷贝完毕后,双方都关闭 inputStream.close(); randomAccessFile.close(); System.out.println("线程"+threadName+"拷贝数据结束,数据段:"+start+"-"+end); } catch (Exception e) { e.printStackTrace(); } } /** * 修复inputstream.skip()缺陷,确保跳过输入流num个字节 */ public static InputStream skipFully(InputStream in,long num)throws Exception{ long remainning = num; long len = 0; while(remainning>0){ len = in.skip(num); remainning -= len; } return in; } }
ExecutorService线程池多线程分段拷贝文件。
猜你喜欢
转载自blog.csdn.net/leadseczgw01/article/details/79115971
今日推荐
周排行