Java高性能编程之NIO三大核心理念

NIO三大核心理念

首先介绍NIO中三个核心组件

  • Buffer缓冲区
  • Channel通道
  • Selector选择器

一、Buffer缓冲区
在这里插入图片描述
1.Buffer 三个重要属性:

  • capacity容量:作为一个内存块,Buffer具有一定的固定大小,也成为“容量”
  • position位置:写入模式时代表写数据的位置。读取模式时,代表读取数据的位置
  • limit限制:写入模式,限制等于buffer的容量。读取模式下,limit等于写入的数据量
    //注意区分不同模式下的含义。

2. ByteBuffer内存类型

  • 直接内存(direct堆外内存):在JVM之外向物理内存直接申请内存
    进行IO或文件IO时比heapBuffer少一次拷贝

ByteBuffrt directByteBuffer = ByteBuffer.allocateDirect(noBNytes);

优点:
1、进行IO或文件IO时比heapBuffer少一次拷贝。(file/socket -> OS memory -> jvm heap)
2、在GC范围之外,降低GC压力,但实现了自动管理。DirextByteBuffer类提供Cleaner对象(PhantomReference),Cleaner被GC前会执行clean方法,触发DirectByteBuffer中定义的Deallocator。

  • 非直接内存(heap堆内存):在JVM的申请内存

建议:性能确实可观的时候才去使用;分配给大型、长寿命;(网络传输、文件读写场景)
通过虚拟机参数MaxDirectMemorySize限制大小,防止耗尽整个机器内存

二、Channel: 通道

和标准的IO Stream区别:在一个通道内进行读取和写入时stream通常是单向的(input和output),可以非阻塞读取和写入通道,通道始终读取或写入缓冲区,channel的API涵盖了UDP/TCP网络和文件IO。(FileCjannel,DatagramCjannel,SocketChannel,ServerSocketChannel)

SocketChannel:用于创建TCP连接,类似java.net.Socket.有两种创建的方式:
1、客户端主动发起和服务的连接。
2、服务端获取新的连接

  • SockerChannel:客户端

//客户端主动发起连接的方式
SocketChannel socketChannel = SocketChannel.open();
//设置为非阻塞模式
socketChannel.configureBlocking(false);
//创建一个端口和ip
socketChannel.connect(new InetSocketAddress(“htttp:163.com”,80));
//发送请求数据 - 向通道写入数据
socketChannel.write(byteBuffer);
//读取服务端返回 - 读取缓冲区的数据
int butesRead = socketChannel.read(byteBuffer);
//关闭连接
socketChannel.close();

write写:非阻塞,write()在尚未写入任何内容可能就返回了。需要在循环中调用
read读:非阻塞,read()方法可能直接返回而根本不读取任何数据,根据返回的int值判断读取了多少字节

  • ServerSocketChannel:服务端

//创建网络服务端
ServerSocketChannel serverSockerChannel = ServerSocketChannel.open();
//设为非阻塞模式
serverSocletChannel.configureBlocking(false);
//绑定端口
serverSocletChannel.socket().bind(new InetSocketAddress(8080));
while(true){
SocketChannel soccketChannel = serverSocletChannel.accept();
if(socketChannel != null){
//TCP请求 读取/响应
}
}
注:serverSocletChannel.accept()如果该通道处于非阻塞,如果没有挂起的连接则该方法立即返回null。
所以必须检查返回的对象是否为空

三、Selector:选择器

  • Selector是一个javaNIO 组件,可以检查一个或多个NIO通道,并确定哪些通道已经准备好进行读取或写入。实现单个线程可以管理多个通道,从而管理多个网络连接。核心概念是事件驱动机制
  • 一个线程使用Selector监听多个channel的不同事件:
    四种事件分别对应SelectionKey四个常量:
    Connect:连接(Selector.OP_CONNECT)
    客户端与服务端建立连接,客户端触发事件
    Accept: 准备就绪(OP_ACCEPT)
    服务端检测到客户端连接请求,服务端触发事件
    Read:   读取(OP_READ)
    客户端与服务端建立连接之后读取操作,双端触发事件
    Write:  写入(OP_WRITE)
    客户端与服务端建立连接之后写入操作,双端触发事件

NIO对比BIO
在这里插入图片描述

四、NIO与多线程结合的改进方案

  • mainReactor接收->分发给subReactor读写->具体业务逻辑分发给单独的线程池处理

总结

   NIO应用于网络应用开发还是比较繁琐,要想将性能提升,还需要和多线程技术结合起来。
因为网络编程本身的复杂性,以及JDK API开发的使用难度较高, 所以在开源社区中,涌出
来很多对JDK NIO进行封装、增强后的网络编程框架,例如:Netty、Mina等。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值