深入理解Java AIO(一)—— Java AIO的简单使用

深入理解AIO系列分为三个部分

  • 第一部分也就是本节的Java AIO的简单使用
  • 第二部分是AIO源码解析(只解析关键部分)(待更新)
  • 第三部分是Linux中的AIO实现

Future和CompletionHandler

Java 异步 IO 提供了两种使用方式,分别是返回 Future 实例和使用回调函数

Future 实例

  • future.isDone();

    判断操作是否已经完成,包括了正常完成、异常抛出、取消

  • future.cancel(true);

    取消操作,方式是中断。参数 true 说的是,即使这个任务正在执行,也会进行中断。

  • future.isCancelled();

    是否被取消,只有在任务正常结束之前被取消,这个方法才会返回 true

  • future.get();

    这是我们的老朋友,获取执行结果,阻塞。

  • future.get(10, TimeUnit.SECONDS);

    如果上面的 get() 方法的阻塞你不满意,那就设置个超时时间。

Futrue这个东西和在线程池里用的应该差不多,不过我暂时没看明白怎么用,也没查到什么资料,之后看一下线程池再过来更新这块。

CompletionHandler 回调函数

java.nio.channels.CompletionHandler 接口定义:

  1. public interface CompletionHandler<V,A> {
  2. // attachment是用来传递参数进去的
  3. void completed(V result, A attachment);
  4. void failed(Throwable exc, A attachment);
  5. }

用法:

  1. AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel.open().bind(null);
  2.  
  3. // accept 方法的第一个参数可以传递 attachment
  4. listener.accept(attachment, new CompletionHandler<AsynchronousSocketChannel, Object>() {
    @Override
  5. public void completed(
  6. AsynchronousSocketChannel client, Object attachment) {
  7. //
  8. }
    @Override
  9. public void failed(Throwable exc, Object attachment) {
  10. //
  11. }
  12. });

简单实例

老样子只贴服务端部分的:

Server

  1. public class Server {
  2.  
  3. public static void main(String[] args) throws IOException {
  4.  
  5. // 实例化,并监听端口
  6. AsynchronousServerSocketChannel server =
  7. AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(8080));
  8.  
  9. // 自己定义一个 Attachment 类,用于传递一些信息
  10. Attachment att = new Attachment();
  11. att.setServer(server);
  12.  
  13. server.accept(att, new CompletionHandler<AsynchronousSocketChannel, Attachment>() {
  14. @Override
  15. public void completed(AsynchronousSocketChannel client, Attachment att) {
  16. try {
  17. SocketAddress clientAddr = client.getRemoteAddress();
  18. System.out.println("收到新的连接:" + clientAddr);
  19.  
  20. // 收到新的连接后,server 应该重新调用 accept 方法等待新的连接进来
  21. att.getServer().accept(att, this);
  22.  
  23. Attachment newAtt = new Attachment();
  24. newAtt.setServer(server);
  25. newAtt.setClient(client);
  26. newAtt.setReadMode(true);
  27. newAtt.setBuffer(ByteBuffer.allocate(2048));
  28.  
  29. // 这里也可以继续使用匿名实现类,不过代码不好看,所以这里专门定义一个类
  30. client.read(newAtt.getBuffer(), newAtt, new ChannelHandler());
  31. } catch (IOException ex) {
  32. ex.printStackTrace();
  33. }
  34. }
  35.  
  36. @Override
  37. public void failed(Throwable t, Attachment att) {
  38. System.out.println("accept failed");
  39. }
  40. });
  41. // 为了防止 main 线程退出
  42. try {
  43. Thread.currentThread().join();
  44. } catch (InterruptedException e) {
  45. }
  46. }
  47. }

ChannelHandler

  1. public class ChannelHandler implements CompletionHandler<Integer, Attachment> {
  2.  
  3. @Override
  4. public void completed(Integer result, Attachment att) {
  5. if (att.isReadMode()) {
  6. // 读取来自客户端的数据
  7. ByteBuffer buffer = att.getBuffer();
  8. buffer.flip();
  9. byte bytes[] = new byte[buffer.limit()];
  10. buffer.get(bytes);
  11. String msg = new String(buffer.array()).toString().trim();
  12. System.out.println("收到来自客户端的数据: " + msg);
  13.  
  14. // 响应客户端请求,返回数据
  15. buffer.clear();
  16. buffer.put("Response from server!".getBytes(Charset.forName("UTF-8")));
  17. att.setReadMode(false);
  18. buffer.flip();
  19. // 写数据到客户端也是异步
  20. att.getClient().write(buffer, att, this);
  21. } else {
  22. // 到这里,说明往客户端写数据也结束了,有以下两种选择:
  23. // 1. 继续等待客户端发送新的数据过来
  24. // att.setReadMode(true);
  25. // att.getBuffer().clear();
  26. // att.getClient().read(att.getBuffer(), att, this);
  27. // 2. 既然服务端已经返回数据给客户端,断开这次的连接
  28. try {
  29. att.getClient().close();
  30. } catch (IOException e) {
  31. }
  32. }
  33. }
  34.  
  35. @Override
  36. public void failed(Throwable t, Attachment att) {
  37. System.out.println("连接断开");
  38. }
  39. }

Attachment

  1. public class Attachment {
  2. private AsynchronousServerSocketChannel server;
  3. private AsynchronousSocketChannel client;
  4. private boolean isReadMode;
  5. private ByteBuffer buffer;
  6. // getter & setter
  7. }

因为网上资料较少,只找到了HongJie大佬的作为参考,所以写不出多少东西,over。

I’m sorry for being so useless too


参考资料:Java 非阻塞 IO 和异步 IO

深入理解Java AIO(一)—— Java AIO的简单使用的更多相关文章

  1. Java提高班(五)深入理解BIO、NIO、AIO

    导读:本文你将获取到:同/异步 + 阻/非阻塞的性能区别:BIO.NIO.AIO 的区别:理解和实现 NIO 操作 Socket 时的多路复用:同时掌握 IO 最底层最核心的操作技巧. BIO.NIO ...

  2. Java核心(一)深入理解BIO、NIO、AIO

    目标: BIO.NIO.AIO 的区别是什么? 同/异步.阻/非阻塞的区别是什么? 文件读写最优雅的实现方式是什么? NIO 如何实现多路复用功能? 一,IO的介绍: (1)IO的全称其实是:Inpu ...

  3. (转)也谈BIO | NIO | AIO (Java版)

    原文地址: https://my.oschina.net/bluesky0leon/blog/132361 关于BIO | NIO | AIO的讨论一直存在,有时候也很容易让人混淆,就我的理解,给出一 ...

  4. 也谈BIO | NIO | AIO (Java版--转)

    关于BIO | NIO | AIO的讨论一直存在,有时候也很容易让人混淆,就我的理解,给出一个解释: BIO | NIO | AIO,本身的描述都是在Java语言的基础上的.而描述IO,我们需要从两个 ...

  5. Java BIO NIO 与 AIO

    回顾 上一章我们介绍了操作系统层面的 IO 模型. 阻塞 IO 模型. 非阻塞 IO 模型. IO 复用模型. 信号驱动 IO 模型(用的不多,知道个概念就行). 异步 IO 模型. 并且介绍了 IO ...

  6. Java面试总结之AIO与NIO

    1.Java NIO 是一种同步非阻塞的I/O模型 将多个IO的阻塞复用到同一个select的阻塞上,从而使得系统在单线程的情况下处理多个客户端请求. NIO三个核心对象:通道(Channel).缓冲 ...

  7. 深入理解BIO、NIO、AIO

    导读:本文你将获取到:同/异步 + 阻/非阻塞的性能区别:BIO.NIO.AIO 的区别:理解和实现 NIO 操作 Socket 时的多路复用:同时掌握 IO 最底层最核心的操作技巧. BIO.NIO ...

  8. 《深入理解Java虚拟机》Java内存区域与内存溢出异常

    注:“蓝色加粗字体”为书本原语 先来一张JVM运行时数据区域图,再接下来一一分析各区域功能:   程序计数器 程序计数器(program Counter Register)是一块较小的内存空间,它可以 ...

  9. 我对面向对象设计的理解——Java接口和Java抽象类

    在没有好好地研习面向对象设计的设计模式之前,我对Java接口和Java抽象类的认识还是很模糊,很不可理解. 刚学Java语言时,就很难理解为什么要有接口这个概念,虽说是可以实现所谓的多继承,可一个只有 ...

  10. 深入理解java虚拟机之java内存区域

    java虚拟机在执行java程序的时候会把它所管理的内存分为多个不同的区域,每个区域都有不同的作用,以及由各自的生命周期,有些随着虚拟机进行的启动而存在,有些区域则依赖于用户线程的启动或结束而建立或销 ...

随机推荐

  1. LeetCode---二叉树3-总结例题

    二叉树-总结例题 1-从中序与后序遍历序列构造二叉树 给定二叉树的后序遍历和二叉树的中序遍历 想法: 先根据后序遍历的最后一个元素构造根节点 寻找根节点在中序遍历中的位置 递归构建根节点的左右子树 / ...

  2. JUC-八锁现象和不安全锁

    1,被 synchronized 修饰的方法,锁的对象是方法的调用者(实例对象) 2,被 static 修饰的方法,锁的对象就是 Class模板对象,这个则全局唯一 问题7: 一个普通同步方法,一个静 ...

  3. 学习经典算法—JavaScript篇(一)排序算法

    前端攻城狮--学习常用的排序算法 一.冒泡排序 优点: 所有排序中最简单的,易于理解: 缺点: 时间复杂度O(n^2),平均来说是最差的一种排序方式: 因为在默认情况下,对于已经排好序的部分,此排序任 ...

  4. 高性能内存队列Disruptor--原理分析

    1.起源     Disruptor最初由lmax.com开发,2010年在Qcon公开发表,并于2011年开源,其官网定义为:"High Performance Inter-Thread ...

  5. Eureka在有虚拟网卡的情况下获取正确的IP

    发现问题 最近项目在Eureka注册时,发现一个问题:注册的IP地址不是 192.168.0.XXX 的网络IP,而是另外一个网段的地址,如图 通过 ipconfig 命令查看本机的IP地址发现,该I ...

  6. iview必备技能一、表单验证规则

    iView表单组件使用async-validator验证器对表单域中数据进行验证,给Form 设置属性 rules,同时给需要验证的 FormItem 设置属性 prop 指向对应字段即可. 完整的验 ...

  7. 教你用纯Java实现一个网页版的Xshell(附源码)

    前言 最近由于项目需求,项目中需要实现一个WebSSH连接终端的功能,由于自己第一次做这类型功能,所以首先上了GitHub找了找有没有现成的轮子可以拿来直接用,当时看到了很多这方面的项目,例如:Gat ...

  8. 智慧港口——基于二三维一体化GIS的港口可视化监管平台

    “智慧港口”是以现代化基础设施设备为基础,以云计算.大数据.物联网.移动互联网.智能控制等新一代信息技术与港口运输业务深度融合为核心,以港口运输组织服务创新为动力,以完善的体制机制.法律法规.标准规范 ...

  9. 2020ubuntu1804server编译安装redis笔记(三)启动服务和使用redis

    第一篇笔记记录了ubuntu1804server编译安装redis5,接下来要配置redis5了 网址:https://www.cnblogs.com/qumogu/p/12435694.html 第 ...

  10. The Game Of Life – 数据结构与算法的敲门砖

    The Game Of Life(生命游戏,又称为细胞自动机)几乎是所有数据结构与算法导论教程前言的一个很经典的程序了.这是一个零玩家游戏,发生在一个平面网格里.每个格子的细胞都有死亡和存活两种状态, ...