自定义nio实现netty分析

先看一个自己用nio实现的netty示例:

1、初始化boss线程池组:

      初始化boss

executor是一个单线程的线程池

selector是多路复用选择器

taskqueue是任务队列,此时还为空

2、初始化worker线程池组,跟boss一样

3、生成ServerSocketChannel

4、往boss里面注册task,并唤醒selector

5、这个就等有客户端请求过来了

public void run() {
   Thread.currentThread().setName(this.threadName);
   //一直循环
   while (true) {
      try {
          //还没有链接
         wakenUp.set(false);
         select(selector);  //会堵塞
         processTaskQueue();
         process(selector);
      } catch (Exception e) {
         // ignore
      }
   }

}

如果有客户端请求,会走processTaskQueue,这个就是执行任务队列里面的任务

public void run() {
   try {
      //注册serverChannel到selector
      serverChannel.register(selector, SelectionKey.OP_ACCEPT);
   } catch (ClosedChannelException e) {
      e.printStackTrace();
   }
}、

就是把serverChannel注册到boss中的selector中去

process(selector);就是处理请求事件

protected void process(Selector selector) throws IOException {
   System.out.println("-------------ssssssssssssssssss---------------");
   Set<SelectionKey> selectedKeys = selector.selectedKeys();
   System.out.println("-------------selectedKeyslen---------------"+selectedKeys.size());
       if (selectedKeys.isEmpty()) {
           return;
       }
       for (Iterator<SelectionKey> i = selectedKeys.iterator(); i.hasNext();) {
           SelectionKey key = i.next();
           i.remove();
           ServerSocketChannel server = (ServerSocketChannel) key.channel();
          // 新客户端
          SocketChannel channel = server.accept();
          // 设置为非阻塞
          channel.configureBlocking(false);
          // 获取一个worker
          Worker nextworker = getSelectorRunnablePool().nextWorker();
          // 注册新客户端接入任务
          nextworker.registerNewChannelTask(channel);
          
          System.out.println("新客户端链接");
       }
}

接收客户端的accept事件,获取SocketChannel,往一个work中插入一个task

nextworker.registerNewChannelTask(channel);

public void registerNewChannelTask(final SocketChannel channel) {
    final Selector selector = this.selector;
    registerTask(new Runnable() {
        @Override
        public void run() {
            try {
                //将客户端注册到selector中
                channel.register(selector, SelectionKey.OP_READ);
            } catch (ClosedChannelException e) {
                e.printStackTrace();
            }
        }
    });
}

并且worker线程也会执行下面这个代码,并且把SocketChannel注册到一个work线程池的selecor中,然后执行读事件

@Override
public void run() {
   Thread.currentThread().setName(this.threadName);
   //一直循环
   while (true) {
      try {
          //还没有链接
         System.out.println("----------processTaskQueue--------"+Thread.currentThread().getName());
         wakenUp.set(false);
         select(selector);
         processTaskQueue();
         System.out.println("----------processTaskQueue--------"+Thread.currentThread().getName());
         process(selector);
      } catch (Exception e) {
         // ignore
      }
   }

}

netty源码

 

 其中pipeline是一个双向链表,是单线程执行的,不会引起并发问题:

红色箭头代表出战,tail---->head     绿色箭头代表入站:head---->tail 

 入站Handle要实现ChannelInboundHandler接口

 出站Handle要实现ChannelOutboundHandler接口

selector.selectedKeys()

// 阻塞等待需要处理的事件发生

selector.select();

// 获取selector中注册的全部事件的 SelectionKey 实例

Set<SelectionKey> selectionKeys = selector.selectedKeys();

selector会去监听所有的channel的事件,当有个channel发来了就绪事件,就会触发selector.select()调用,而且会有一个延迟,所以selector.selectedKeys()出来的是一个集合,而不是一个一个的找出就绪事件

netty中boss线程多个 

 netty中boss线程多个 ,则需要开多个端口,否则只有一个线程生效

如:boss线程数设置为2时:

ChannelFuture cf = bootstrap.bind(9000).sync();
ChannelFuture cf1 = bootstrap.bind(9001).sync(); 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值