Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4041089
  • 博文数量: 366
  • 博客积分: 9916
  • 博客等级: 中将
  • 技术积分: 7195
  • 用 户 组: 普通用户
  • 注册时间: 2011-05-29 23:27
个人简介

简单!

文章分类

全部博文(366)

文章存档

2013年(51)

2012年(269)

2011年(46)

分类: Java

2012-11-29 15:56:38

      Netty网络线程模型主要有两类线程组成:boss线程、worker线程。启动一 个server实例只会产生一个boss线程,boss线程主要负责监听端口,当有新的连接请求时就会产生一个task交给worker线程池处 理,worker线程池中线程的个数默认是cpu个数的2倍。


       Netty网络I/O操作采用了目前流行的I/O多路选择器Selector方式(具体的实现是select/poll,还是epoll/kqueue,是由java虚拟机根据具体操作系统的实现来决定的)。

       Worker线程池中每个线程都维护几个处理队列(如注册队列,写任务队列等),每个队列中实际上都注册着一些interestOPS(感兴趣的操作 集),worker线程不断的循环地做select操作,boss线程不断地将新的连接请求注册到一个work线程的注册队列中,每次都是轮询出worker线程池中的一个线程:

  1. NioWorker nextWorker() {
  2.    return workers[Math.abs(workerIndex.getAndIncrement() % workers.length)];
  3. }

        Worker线程中如果selectors.keys操作结果为空,则会主动退出,当又有新的连接请求被boss线程加到相应的worker线程的队列时,该worker线程又会重新启动。

       这里在处理线程间同步和互斥时用了2个锁:

  1.  一个started标志,主要用于判断当前线程是否已经启动,当boss线程选择 了一个worker线程后,想把新请求加入到该worker线程的新请求队列时,若该started=false,则表示该worker线程没有启动,所 以要先启动worker线程,若started=true,则表示该worker线程已启动,则直接把请求加入到该worker线程的请求队列就行了。当 worker线程的队列中没有了操作,即为空时,worker线程会主动退出,并设置started=false。故,对于started,boss线程 和worker线程间要进行同步,所以使用了       synchronized(startStopLock)
  2.  Selectors选择器操作本身是同步的,但对selectionkey的操作则需要进行同步控制,所以又用到了一个锁:selectorGuard = newReentrantReadWriteLock()

 

第一个是互斥锁;第二个是读写锁。

每个worker线程各自使用一个selector,即每个worker线程的请求队列中所有的新请求(即一个SocketChannelclient)都会在该worker线程的Selector中注册感兴趣的选择键集。

 

注:一个Channel对应一个SelectionKey,Selector维护的是所有Channel的SelectionKey,即维护的是一个SelectionKey的集合Set

阅读(10324) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~