通过IO和NIO对于文件的copy

ExecutorService是非常好用的并发工具,在并行的环境下我们经常通过ExecutorService去回调执行任务。

ExecutorService的任务机制


通过IO和NIO对于文件的copy
 我现在有一本鸟哥私房菜的Linux书籍大约80M,我想通过3种方式(IO、NIO、NIO buffer),期待是在80ms内完成。

Solution 1: Stream Copy

 

	public static void copy(String in, String out) throws Exception {
		FileInputStream fin = new FileInputStream(in);
		FileOutputStream fout = new FileOutputStream(out);

		byte[] buf = new byte[4096];
		int read;
		while ((read = fin.read(buf)) > -1) {
			fout.write(buf, 0, read);
			if (Thread.interrupted()) {
				throw new IOException("Thread interrupted, cancelling");
			}
		}

		fin.close();
		fout.close();
	}

 print:

invokeAll finished after: 83
java.io.IOException: Thread interrupted, cancelling
	at org.dxy.nio.FileUtil.copy(FileUtil.java:29)
	at org.dxy.nio.FileUtil$1.call(FileUtil.java:73)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
	at java.util.concurrent.FutureTask.run(FutureTask.java:138)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)
Future.isCancelled? true
Call really finished after: 84
Threads still active: 0

Solution 2: NIO with transfer

 

this answer at StackOverflow说过:

“Don’t use a buffer if you don’t need to. Why copy to memory if your target is another disk or a NIC? With larger files, the latency incured is non-trivial. (…) Use FileChannel.transferTo() or FileChannel.transferFrom(). The key advantage here is that the JVM uses the OS’s access to DMA (Direct Memory Access), if present. (This is implementation dependent, but modern Sun and IBM versions on general purpose CPUs are good to go.) What happens is the data goes straight to/from disc, to the bus, and then to the destination…by passing any circuit through RAM or the CPU.”

 

private static void copyNioNoBuffered(String in, String out)
			throws Exception {
		FileChannel fin = new FileInputStream(in).getChannel();
		FileChannel fout = new FileOutputStream(out).getChannel();

		fout.transferFrom(fin, 0, new File(in).length());

		fin.close();
		fout.close();
	}

 print:

 

 

invokeAll finished after: 1355
Future.isCancelled? true
java.nio.channels.ClosedByInterruptException
	at java.nio.channels.spi.AbstractInterruptibleChannel.end(AbstractInterruptibleChannel.java:184)
	at sun.nio.ch.FileChannelImpl.write(FileChannelImpl.java:656)
	at sun.nio.ch.FileChannelImpl.transferFromFileChannel(FileChannelImpl.java:542)
	at sun.nio.ch.FileChannelImpl.transferFrom(FileChannelImpl.java:603)
	at org.dxy.nio.FileUtil.copyNioNoBuffered(FileUtil.java:42)
	at org.dxy.nio.FileUtil.access$0(FileUtil.java:37)
	at org.dxy.nio.FileUtil$1.call(FileUtil.java:73)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
	at java.util.concurrent.FutureTask.run(FutureTask.java:138)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)
Call really finished after: 1373
Threads still active: 0

 Solution 3 – NIO with Buffering

 

	private static void copyNioBuffered(String in, String out) throws Exception {
		FileChannel fin = new FileInputStream(in).getChannel();
		FileChannel fout = new FileOutputStream(out).getChannel();

		ByteBuffer buff = ByteBuffer.allocate(4096);
		while (fin.read(buff) != -1 || buff.position() > 0) {
			buff.flip();
			fout.write(buff);
			buff.compact();
		}

		fin.close();
		fout.close();
	}

 print:

java.nio.channels.ClosedByInterruptException
invokeAll finished after: 85
	at java.nio.channels.spi.AbstractInterruptibleChannel.end(AbstractInterruptibleChannel.java:184)
	at sun.nio.ch.FileChannelImpl.read(FileChannelImpl.java:152)
	at org.dxy.nio.FileUtil.copyNioBuffered(FileUtil.java:53)
Future.isCancelled? true
	at org.dxy.nio.FileUtil.access$0(FileUtil.java:48)
	at org.dxy.nio.FileUtil$1.call(FileUtil.java:73)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
	at java.util.concurrent.FutureTask.run(FutureTask.java:138)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)
Call really finished after: 86
Threads still active: 0

 

你可能感兴趣的:(java,IO,nio,performance)