Netty的EventLoop和EventLoopGroup

EventLoopGroup : 事件循环组

EventLoop:事件循环

  1. 1个EventLoopGroup中包含1个或多个EventLoop
  2. 1个EventLoop在它的整个生命周期当中只会与唯一一个Thread进行绑定
  3. 所有由EventLoop所处理的各种I/O事件都将在它关联的那个Thread上进行处理。
  4. 一个Channel在它的整个生命周期中只会注册在一个EventLoop上。
  5. 一个EventLoop在运行过程当中,会被分配给一个或多个Channel。

总结:绝对不要在handler中做任何耗时的工作,一旦发生就会将EventLoop中的线程给卡在耗时的事件上,这样其他许多channel的I/O事件都会等待,

解决办法:在handler中启动一个线程池

 

PS:当你去执行Channel上的任何一个操作时,netty一定会首先去判断执行这个操作的线程是否就是Channel所对应的EventLoop所包含的线程,如果是则直接执行,否则netty以一个任务的形式提交给EventLoop,最终执行这个任务的线程还是EventLoop中的线程,通过这样精巧的设计,netty在整个channel的操作上消除了所有的需要同步的地方。

 

重要结论:在Netty中,channel的实现一定是线程安全的,基于此,我们可以存储一个channel的引用,并且在需要向远程端点发送数据时,通过这个引用来调用channel相应的方法;即便当时有很多线程都在使用它也不会出现多线程问题;而且,消息一定会按照顺序发送出去。

 

重要结论2:我们在业务开发中,不要将长时间执行的耗时任务放入到EventLoop的执行队列中,因为它将会一直阻塞该线程对应的所有channel上的其他执行任务,如果我们需要执行阻塞调用或是耗时的操作(开发中常见),那么我们就需要使用一个专门的EventExecutor(业务线程池)。

 

:EventExecutor的两种实现方式

1. 在ChannelHandler的回调方法中,使用自己定义的业务线程池,这样就可以实现异步调用

2.借助netty提供的向ChannelPipeline添加ChannelHandler时调用addLast方法来传递EventExecutor.

 

说明:默认情况下(调用addLast(handler)),channelHandler中的回调发放都是由I/O线程所执行,如果调用了ChannelPipeline addLast(EventExecutorGroup group,ChannelHandler .. handlers)方法,那么ChannelHandler中的回调方法就是由参数中的group线程组来执行的。

你可能感兴趣的:(netty,java)