欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

jdk8多线程操作文件 jdk多线程文件 

程序员文章站 2022-07-09 14:58:47
...
今天同事让我帮看看多线程读写文件,尝试着写了一个实例。操作的文件以块形式进行处理,块大小等于缓存大小,线程池根据cpu决定池大小。

/**
 * Created on 2016年3月18日
 */
package org.zl.test;

import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.EnumSet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 文件以块形式进行处理,块大小等于缓存大小
 * 
 * 采用FileChannel的map方式读写文件
 * 线程池根据cpu决定池大小
 *  
 * <br>
 * change log:<br>
 * 0.01 2016年3月18日 Created <br>
 * @version 0.01
 * @author Leo
 */
public class FileRW {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception{
		int bufferSize = 1024 * 1024;//块大小

		Path copy_from = Paths.get("d:\\web\\ajaxswing410.zip");
		//Path copy_from = Paths.get("d:\\license.txt");
		Path copy_to = Paths.get("d:\\data2.zip");
		//Path copy_to = Paths.get("d:\\l.txt");
		
		FileChannel fileChannel_from = FileChannel.open(copy_from,EnumSet.of(StandardOpenOption.READ));
		Files.deleteIfExists(copy_to);
		FileChannel fileChannel_to = FileChannel.open(copy_to,EnumSet.of(StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE)); 
		ExecutorService executor = Executors.newWorkStealingPool();
		
		//分任务块
		long filesize = fileChannel_from.size();
		long bytesCount = 0;
		//List<Runnable> callables = Arrays.asList();
		while(filesize>bytesCount){
			long length=(filesize<(bytesCount+bufferSize))?filesize-bytesCount:bufferSize;
			Runnable task = new MyThread(fileChannel_from,fileChannel_to,bytesCount,length);
			executor.submit(task);
			bytesCount = bytesCount+bufferSize;
		}
		
		//线程结束关闭通道
		while(!executor.isShutdown()){
			executor.shutdown();
			TimeUnit.SECONDS.sleep(2);
		}
		fileChannel_from.close();
		fileChannel_to.close();
	}

}
class MyThread implements Runnable{

	FileChannel fileChannel_from;
	FileChannel fileChannel_to;
	long offset;
	int length;
	
	
	/**
	 * 
	 * @param fileChannel_from 读通道
	 * @param fileChannel_to 写通道
	 * @param offset 起点
	 * @param length 长度
	 */
	public MyThread(FileChannel fileChannel_from,FileChannel fileChannel_to,long offset,long length) {
		this.fileChannel_from =fileChannel_from;
		this.fileChannel_to =fileChannel_to;
		this.offset=offset;
		this.length=Long.valueOf(length).intValue();
	}
	
		/* (non-Javadoc)
		 * @see java.lang.Runnable#run()
		 */
		@Override
		public void run() {
			long startTime = System.nanoTime();
			//ByteBuffer bytebuffer = ByteBuffer.allocate(length);
			//ByteBuffer bytebuffer = ByteBuffer.allocateDirect(TestThread.bufferSize);
			//bytebuffer.flip();
			try {
				System.out.println("read:"+length);
				//fileChannel_from.read(bytebuffer, offset);
				MappedByteBuffer buffer = fileChannel_from.map(FileChannel.MapMode.READ_ONLY,offset,length);
				fileChannel_to.write(buffer,offset);
				
				//bytebuffer.clear();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		    String threadName = Thread.currentThread().getName();
		    long elapsedTime = System.nanoTime() - startTime;
		    System.out.println(threadName+" Elapsed Time is " + (elapsedTime / 1000000000.0) + " seconds");
		}
	
}



程序只做为测试,不够严谨。欢迎提意见和改进想法,看看java新特性是否能提供更便捷的代码操作。