AIO入门实例
来源:互联网 发布:詹姆斯历年数据 编辑:程序博客网 时间:2024/06/05 11:07
AIO入门实例
摘要:阅读《Netty权威指南》笔记
AIO概念:
AIO即JDK7开始引入的NIO,提供了异步文件通道和异步到街子通道的实现。异步通道提供两种方式操作结果:
- 通过java.util.concurrent.Future类来表示异步操作的结果;
- 在执行异步操作时传入一个java.nio.channels.CompletionHandler接口的实现类作为操作完成的回调(本例子主要使用这个方法)。
AIO创建的TimeServer
public class TimeServer { public static void main(String[] args) { int port = 8080; if (args != null && args.length > 0) { try { port = Integer.valueOf(args[0]); } catch (NumberFormatException e) { } } AsyncTimeServerHander timeServerHander = new AsyncTimeServerHander(port); new Thread(timeServerHander, "AIO-AsyncTimeServerHandler-001").start(); }}
很简单,就是初始化一个线程,接下来看AsyncTimeServerHander 的实现代码:
public class AsyncTimeServerHander implements Runnable { private int port; CountDownLatch latch; AsynchronousServerSocketChannel asynchronousServerSocketChannel; /** * 构造方法,创建一个异步的服务端通道AsynchronousServerSocketChannel,调用它的bind方法绑定监 * 听端口,绑定成功则打印提示到输入台 * * @param port */ public AsyncTimeServerHander(int port) { this.port = port; try { asynchronousServerSocketChannel = AsynchronousServerSocketChannel.open(); asynchronousServerSocketChannel.bind(new InetSocketAddress(port)); System.out.println("The time server is start in port " + port); } catch (IOException e) { e.printStackTrace(); } } @Override public void run() { //阻塞当前线程,防止服务端异常退出 latch = new CountDownLatch(1); doAccept(); try { latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } } /** * 连接客户端的方法,采用的CompletionHandler方法,接收AcceptCompletionHandler作为采用的CompletionHandler方 * 法实例 */ public void doAccept() { asynchronousServerSocketChannel.accept(this, new AcceptCompletionHandler()); }}
CompletionHandler接口有两个方法:
public void completed(AsynchronousSocketChannel result, AsyncTimeServerHander attachment)
public void failed(Throwable exc, AsyncTimeServerHander attachment)
根据方法名很容易就能理解两个方法的执行时间。
接下来看整个AcceptCompletionHandler
的代码:
public class AcceptCompletionHandler implements CompletionHandler<AsynchronousSocketChannel, AsyncTimeServerHander> { @Override public void completed(AsynchronousSocketChannel result, AsyncTimeServerHander attachment) { /** * 接收客户端请求,因为AsynchronousServerSocketChannel可以接收成千上万的客户端, * 所以回调AsyncTimeServerHander中asynchronousServerSocketChannel.accept方法, * 让新的客户端继续接入,最终形成一个循环 */ attachment.asynchronousServerSocketChannel.accept(attachment, this); ByteBuffer buffer = ByteBuffer.allocate(1024); /**异步读操作 * 第一个buffer:接收缓冲区 * 第二个buffer:异步Channel携带的附件,通知回调的时候作为入参使用(我的理解是当该Channel继续被调用时的参数) * CompletionHandler:接收通知回调的业务Handler,这里的实现类是ReadCompletionHandler */ result.read(buffer, buffer, new ReadCompletionHandler(result)); } @Override public void failed(Throwable exc, AsyncTimeServerHander attachment) { attachment.latch.countDown(); }}
从AcceptCompletionHandler
就可以看出,主要是通过不断的回调来实现非阻塞,同时不会对像NIO那样需要不断的判断连接的状态去根据具体的状态分配Handler。
继续往下看ReadCompletionHandler
public class ReadCompletionHandler implements CompletionHandler<Integer, ByteBuffer> { private AsynchronousSocketChannel channel; /** * 构造方法:将AsynchronousSocketChannel作为构造方法的参数传入,作为成员变量使用, * 主要用于半包消息和发送应答 * * @param channel */ public ReadCompletionHandler(AsynchronousSocketChannel channel) { if (channel != null) { this.channel = channel; } } /** * 读取到消息的处理 * * @param result * @param attachment */ @Override public void completed(Integer result, ByteBuffer attachment) { attachment.flip(); byte[] body = new byte[attachment.remaining()]; attachment.get(body); try { String req = new String(body, "UTF-8"); System.out.println("The time server receive order : " + req); //消息判断,如果是正确的消息,调用doWrite发送当前消息到客户端 String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(req) ? new Date(System.currentTimeMillis()).toString() : "BAD ORDER"; doWrite(currentTime); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } /** * 发送消息到客户端 * * @param currentTime */ private void doWrite(String currentTime) { if (currentTime != null && currentTime.trim().length() > 0) { byte[] bytes = currentTime.getBytes(); ByteBuffer writeBuffer = ByteBuffer.allocate(1024); writeBuffer.put(bytes); writeBuffer.flip(); channel.write(writeBuffer, writeBuffer, new CompletionHandler<Integer, ByteBuffer>() { @Override public void completed(Integer result, ByteBuffer attachment) { //递归调用,如果没有发送完成,继续发送 if (attachment.hasRemaining()) { channel.write(attachment, attachment, this); } } @Override public void failed(Throwable exc, ByteBuffer attachment) { try { channel.close(); } catch (IOException e) { //ingore on close } } }); } } @Override public void failed(Throwable exc, ByteBuffer attachment) { try { this.channel.close(); } catch (IOException e) { e.printStackTrace(); } }}
ReadCompletionHandler
的主要功能已经在代码里注释好了,理解起来也不是很难
总结
- AIO使用起来逻辑上很好理解,但是因为有很多的匿名函数,导致代码看起来很复杂;
- AIO非阻塞的思想其实和NIO一样,都是通过不断轮询
AsynchronousServerSocketChannel
的accept
方法获取连接,分配对应的Handler
去处理业务; - demo很简单,重要的是对代码的理解以及熟练使用API。
阅读全文
0 0
- Java AIO 入门实例
- AIO入门实例
- BIO NIO AIO实例
- jdk7 AIO 入门
- java aio 入门
- Netty入门--AIO
- Java AIO编程入门
- JDK7 AIO初体验实例
- JDK7 AIO初体验实例
- AIO
- aio
- AIO
- AIO
- AIO
- JDK7 AIO 入门(一)------AsynchronousFileChannel
- JDK7 AIO 入门(二)------AsynchronousServerSocketChannel
- JDK7 AIO 入门(一)------AsynchronousFileChannel
- JDK7 AIO 入门(二)------AsynchronousServerSocketChannel
- MFC与.net比较
- IO流——BufferedWriter和BufferedReader
- 6.序列!序列!
- UE4_VR传送
- Spring-Boot + Swagger2 自动生成API接口文档
- AIO入门实例
- css样式整体设置
- HTML5_CSS入门(尺寸大小、颜色单位、溢出、哪些元素可以设置尺寸、边框,边框倒角、边框阴影,轮廓)
- Docker Toolbox
- Django QuerySet API
- oracle笔记1-基本用户、权限、表操作
- java简易excel导入导出工具(封装POI)
- Android PATH and ld path
- 百度开发者API接口:获取经纬度和详细地理位置(Geocoding API和IP定位API)