Java 压缩20M文件从30秒到1秒的优化过程,还不相信?( 三 )


//Version 4 使用Map映射文件public static void zipFileMap() {//开始时间long beginTime = System.currentTimeMillis();File zipFile = new File(ZIP_FILE);try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));WritableByteChannel writableByteChannel = Channels.newChannel(zipOut)) {for (int i = 0; i < 10; i++) {zipOut.putNextEntry(new ZipEntry(i + SUFFIX_FILE));//内存中的映射文件MappedByteBuffer mappedByteBuffer = new RandomAccessFile(JPG_FILE_PATH, "r").getChannel().map(FileChannel.MapMode.READ_ONLY, 0, FILE_SIZE);writableByteChannel.write(mappedByteBuffer);}printInfo(beginTime);} catch (Exception e) {e.printStackTrace();}}
打印如下
---------MapfileSize:20Mconsum time:1305
可以看到速度和使用的速度差不多的 。
使用Pipe
Java NIO 管道是2个线程之间的单向数据连接 。Pipe有一个通道和一个sink通道 。其中通道用于读取数据 , sink通道用于写入数据 。可以看到源码中的介绍 , 大概意思就是写入线程会阻塞至有读线程从通道中读取数据 。如果没有数据可读 , 读线程也会阻塞至写线程写入数据 。直至通道关闭 。
Whether or not a thread writing bytes to a pipe will block until anotherthread reads those bytes
image
我想要的效果是这样的 。源码如下
//Version 5 使用Pippublic static void zipFilePip() {long beginTime = System.currentTimeMillis();try(WritableByteChannel out = Channels.newChannel(new FileOutputStream(ZIP_FILE))) {Pipe pipe = Pipe.open();//异步任务CompletableFuture.runAsync(()->runTask(pipe));//获取读通道ReadableByteChannel readableByteChannel = pipe.source();ByteBuffer buffer = ByteBuffer.allocate(((int) FILE_SIZE)*10);while (readableByteChannel.read(buffer)>= 0) {buffer.flip();out.write(buffer);buffer.clear();}}catch (Exception e){e.printStackTrace();}printInfo(beginTime);}//异步任务public static void runTask(Pipe pipe) {try(ZipOutputStream zos = new ZipOutputStream(Channels.newOutputStream(pipe.sink()));WritableByteChannel out = Channels.newChannel(zos)) {System.out.println("Begin");for (int i = 0; i < 10; i++) {zos.putNextEntry(new ZipEntry(i+SUFFIX_FILE));FileChannel jpgChannel = new FileInputStream(new File(JPG_FILE_PATH)).getChannel();jpgChannel.transferTo(0, FILE_SIZE, out);jpgChannel.close();}}catch (Exception e){e.printStackTrace();}}
总结