【netty in action】学习笔记-第一章 了解java NIO(2)

【netty in action】学习笔记-第一章 了解java NIO(2)

上一篇文章了解了java nio的一些特性和基本用法。本篇继续来看看java nio有哪些问题以及netty如何解决这些问题。

跨平台和兼容性问题

java nio有nio和nio2两个版本,后者只支持jdk7。而且java nio本身属于比较low level的api,有时候会遇到在linux运行良好但是在windows上却有问题。

netty提供统一的api,你不需要关注java的版本,也不需要关注操作系统。

ByteBuffer的扩展

通过前面的示例,你能看出来java nio的ByteBuffer并不好用,比如还有自己切换读写模式。netty扩展了ByteBuffer提供更加易用的API。具体的用法在后面章节的笔记中会详细说明。

内存泄漏的问题

nio有个Scattering and Gathering的概念,就是分散读取,集中写入。

在这里插入图片描述
在这里插入图片描述

scatter(分散)是指数据从一个channel读取到多个buffer中。比如下面的例子:

ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body = ByteBuffer.allocate(1024);
ByteBuffer[] bufferArray = { header, body }
channel.read(bufferArray);

read()方法按照buffer在数组中的顺序将从channel中读取的数据写入到buffer,当一个buffer被写满后,channel紧接着向另一个buffer中写。

集中读的概念就是反过来,多个buffer的数据写入到同一个channel。示例如下:

ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body = ByteBuffer.allocate(1024);
ByteBuffer[] bufferArray = { header, body };
channel.write(bufferArray);

java nio提供了专门的接口来处理Scattering and Gathering

public interface ScatteringByteChannel extends ReadableByteChannel
{
    public long read(ByteBuffer[] dsts) throws IOException;

    public long read(ByteBuffer[] dsts, int offset, int length) throws IOException;
}

public interface GatheringByteChannel extends WritableByteChannel
{
    public long write(ByteBuffer[] srcs) throws IOException;

    public long write(ByteBuffer[] srcs, int offset, int length) throws IOException;
}

比如SocketChannel就实现了这两个接口。

在这里插入图片描述

但是Scattering and Gathering功能会导致内存泄露,一直到Java7才解决内存泄露问题。

epoll的缺陷问题

这是个著名的bug,它会导致Selector空轮询,最终导致CPU 100%。官方声称在JDK1.6版本的update18修复了该问题,但是直到JDK1.7版本该问题仍旧存在,只不过该BUG发生概率降低了一些而已,它并没有被根本解决。

while (true) {
            int selected = selector.select();
            Set<SelectedKeys> readyKeys = selector.selectedKeys();
            Iterator iterator = readyKeys.iterator();
            while (iterator.hasNext()) {
            //do something
            }
        }

解决epoll bug的唯一方法是回收旧的选择器,将先前注册的通道实例转移到新创建的选择器上。而netty正是基于此方法提供的解决方案。

netty 对Selector的select操作周期进行统计,每完成一次空的select操作进行一次计数,若在某个周期内连续发生N次空轮询,则触发了epoll死循环bug。

然后netty会重建Selector,判断是否是其他线程发起的重建请求,若不是则将原SocketChannel从旧的Selector上去除注册,重新注册到新的Selector上,并将原来的Selector关闭。

这个问题的详细情况和解决方案,就不做这里展开了,有兴趣的可以网上搜索下。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值