网络编程之AIO
AIO的思想是一个线程处理一个有效请求,当有连接请求时,由系统来通知应用程序处理请求完成连接,而不需要向NIO一样进行轮询,IO请求也是由系统进行处理,处理完成后通过回调机制通知应用程序直接调用这些数据,这里就是使用到了异步的思想。AIO适用于连接数量多并且连接时间长的场景。
代码思路:
- 建立一个线程池转化为
AsynchronousChannelGroup
,我这里使用的是newCachedThreadPool
线程池 - 建立一个
AsynchronousServerSocketChannel
绑定线程池和端口 - 调用accept,将发生连接请求要执行的执行器(实现
completionHandler
)钩到系统中 - 调用
AsychronousSocketChannel
的read或write,将发送读写事件时要执行的执行器钩到通道上 - 最后为了不让程序退出,使用while死循环
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousChannelGroup;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ServerWithThreadGroup {
public static void main(String[] args) throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
AsynchronousChannelGroup threadGroup = AsynchronousChannelGroup.withCachedThreadPool(executorService, 1);
final AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel
.open(threadGroup)
.bind(new InetSocketAddress(8888));
//绑定执行器,当有连接请求时执行该程序
serverChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Object>() {
@Override
public void completed(AsynchronousSocketChannel client, Object attachment) {
serverChannel.accept(null, this);
try {
System.out.println(client.getRemoteAddress());
ByteBuffer buffer = ByteBuffer.allocate(1024);
//绑定执行器,当有读操作时执行该程序
client.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
@Override
public void completed(Integer result, ByteBuffer attachment) {
attachment.flip();
System.out.println(new String(attachment.array(), 0, result));
client.write(ByteBuffer.wrap("HelloClient".getBytes()));
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
exc.printStackTrace();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void failed(Throwable exc, Object attachment) {
exc.printStackTrace();
}
});
while (true) {
Thread.sleep(1000);
}
}
}
总结:
AIO的编程思路比较清晰,只要将对应的执行器注册到系统中就行了,注册完后主程序该干嘛干嘛去了,实现了异步。这里要注意的是ByteBuffer使用起来较为复杂而且坑比较多,而在Netty中对其进行了封装优化。Netty的编程思路与AIO类似,不过它底层使用的是NIO模式。