setPipeline setPipelineFactory区别

从源码看:
setPipeline将参数传入setPipelineFactory,依旧实现了setPipelineFactory的方法,
从方法的注释可了解:
setPipeline在一个Channel创建的时候,clone一个被设置过的默认的ChannelPipeline和Channel进行关联。因此实际传入 setPipelineFactory的pipeline参数是Bootstrap自身的私有属性pipeline。
setPipelineFactory则是在一个Channel创建的时候,从内部被实现的 getPipeline()中返回一个ChannelPipeline与Channel进行关联。
因此不难理解,虽然在ServerBootstrap.channelOpen中都是调用的 getPipelineFactory(),但前者每次通过 getPipeline()返回的是Bootstrap私有属性pipeline的一个clone版本,仅复制了ChannelHandler的引用到
一个新的ChannelPipeline中,也就是ChannelPipeline的hashcode不同,但是ChannelHandler的内容一样,不过一旦分配后,在Channel中后续对其自己所关联的ChannelPipeline的操作就与Bootstrap默认的无关的。
而后者每次通过 getPipeline()返回的则是自定义被实现的全新实例,当前和以后都与其他的Channel的ChannelHandler无关。

还有一种类似作弊的操作,则是在自定义的ChannelPipelineFactory中返回一个静态的ChannelPipeline,这种情况则使得Bootstrap全局只使用同一个ChannelPipeline,在任何Channel中对ChannelPipeline的
操作都会直接更新到其他所有的Channel中的ChannelPipeline。不过此时需要自定义重写一个ChannelPipeline,在这个自定义类中,取消Channel和ChannelPipeline的attch关系,也就是一对一绑定关系。

官方的使用建议:
前者的使用适合(或仅仅是方便的意思)只有一个channel(例如一次性的client-side端),或者Channel是无连接的,或者涉及的ChannelHandles是无状态的。
而如果涉及的ChannelHandles有一个或多个是有状态需求的,或者将会创建多个Channel(例如server-side端) ,则必须用后者。

注意到在 setPipelineFactory的时候,方法中将私有的pipeline属性设置成了null,至于为什么在server-side端建议必须要用 setPipelineFactory,很有可能是出于每次接收到Channel后创建ChannelPipeline的
开销考虑,因为 setPipeline的情况下,给私有属性pipelineFactory赋值的是默认的 pipelineFactory(pipeline)方法,而默认方法每次都需要遍历传入的pipeline从而对一个newPipeline进行浅拷贝赋值,无法进行
优化。而直接使用 setPipelineFactory,则省去了这部分开销。

其中Bootstrap自带的pipeline是线程安全的,其由 volatile 修饰(写不安全,读可见) ,而ChannelPipeline的写是带 synchronized 修饰的。

你可能感兴趣的:(setPipeline setPipelineFactory区别)