这人间岁岁年年 永不停歇变换
我眼前世相万千 但没有太多灵感
这景色从北到南 永不重复流转
...... 上次说到AIO,并做了开篇的简短介绍,今天接着聊 AIO,一种异步非阻塞IO在这里回忆下前面所说的BIO和NIO,分别是同步阻塞IO和同步非阻塞IO,NIO在BIO的基础上实现了对于自身的一个非阻塞操作,然而对于程序来说,无论是是BIO或者是NIO,其过程依然是一个同步的过程,例如读写文件,程序进程在读写文件时,总是一个同步操作,需要读取/写入完毕或者发生异常时,才能做其他的事,类似下面过程:
前面聊天小程序也是一样,当客户端尝试连接服务端的时候,必须要等到服务端给出响应,那么客户端才结束方法的执行,即:
简言之,类似网页前端向服务端发起的AJAX请求,这是个客户端向服务端发送的一个 “同步的Ajax请求”。
那么AIO则提供了一个“异步的Ajax请求”,怎么理解这句话?读写文件或者TCP连接总是立马返回,不会存在同步等待。
即,读写文件变成这样:
聊天小程序,TCP连接成这样:
下面,以文件复制为例,代码说明下:
package com.lgli.aio.api;import java.nio.ByteBuffer;import java.nio.channels.AsynchronousFileChannel;import java.nio.channels.CompletionHandler;import java.nio.file.Paths;import java.nio.file.StandardOpenOption;import java.util.concurrent.CountDownLatch;import java.util.concurrent.Future;/** * AioApi * @author lgli */public class AioApi {
public static void main(String[] args) throws Exception{
// copyFileAsyncChannelByFuture(); copyFileAsyncChannelByCompletionHandler(); } /** * 异步复制文件二 * @throws Exception */ private static void copyFileAsyncChannelByCompletionHandler() throws Exception{
//打开异步文件读取通道 AsynchronousFileChannel channel = AsynchronousFileChannel.open(Paths.get("F:\\entertainment\\movie\\马达加斯加的企鹅.mkv"), StandardOpenOption.READ); //打开异步文件写入通道 AsynchronousFileChannel writeChannel = AsynchronousFileChannel.open(Paths.get("F:\\entertainment\\movie\\马达加斯加的企鹅-AIO-HAND.mkv"), StandardOpenOption.WRITE,StandardOpenOption.READ,StandardOpenOption.CREATE); ByteBuffer byteBuffer = ByteBuffer.allocate(1048576); long position = 0l; while(true){
CountDownLatch downLatch = new CountDownLatch(1); channel.read(byteBuffer, position, byteBuffer, new CompletionHandler() {
@Override public void completed(Integer result, ByteBuffer attachment) {
downLatch.countDown(); System.out.println("读取完成"); } @Override public void failed(Throwable exc, ByteBuffer attachment) {
System.err.println("读取失败"); } }); downLatch.await(); byteBuffer.flip(); CountDownLatch downLatchs = new CountDownLatch(1); writeChannel.write(byteBuffer, position, byteBuffer, new CompletionHandler() {
@Override public void completed(Integer result, ByteBuffer attachment) {
System.out.println("写入完成"); downLatchs.countDown(); byteBuffer.clear(); } @Override public void failed(Throwable exc, ByteBuffer attachment) {
System.err.println("写入失败"); } }); position += byteBuffer.limit(); downLatchs.await(); System.out.println(writeChannel.size()+"-------"+channel.size()); System.out.println(position); if(writeChannel.size() >= channel.size()){
break; } } System.out.pri