Java netty的并发编码

Java netty的并发编码,java,concurrency,netty,Java,Concurrency,Netty,编码器的编码方法会并发执行吗?我观察到编码方法可能由不同的线程并发。管道定义为: Channels.pipeline( idleHandler, new AmfDecoder<GameEvent>(GameEvent.class), new AmfEncoder<GameEvent>(), concurrencyHandler, new WebHandler()); Channels.pipeline( 懒汉, 新AmfDecod

编码器的编码方法会并发执行吗?我观察到编码方法可能由不同的线程并发。管道定义为:

Channels.pipeline(
    idleHandler,
    new AmfDecoder<GameEvent>(GameEvent.class),
    new AmfEncoder<GameEvent>(),
    concurrencyHandler,
    new WebHandler());
Channels.pipeline(
懒汉,
新AmfDecoder(GameEvent.class),
新的AmfEncoder(),
山德勒,
新的WebHandler());
编码器:

public class AmfEncoder<T extends IAmfEvent> extends OneToOneEncoder{
private final SerializationContext serializationContext = new SerializationContext();
private final Amf3Output amfout = new Amf3Output(serializationContext);

@Override
protected Object encode(ChannelHandlerContext arg0, Channel arg1,
        Object arg2) throws Exception {
    T e = (T)arg2;
    ByteArrayOutputStream byteoutStreamSize = new ByteArrayOutputStream();
    amfout.setOutputStream(byteoutStreamSize);
    amfout.writeObject(e.getBody());
    // byteoutStreamSize has small probability become empty at here, in debug mode I can sure e.getBody() has data
    // I thought byteoutStreamSize might be empty by another thread call "amfout.flush()" or "amfout.reset()"
    amfout.flush();
    //...
    amfout.reset();
}
public类AmfEncoder扩展了onetoneencoder{
private final SerializationContext SerializationContext=新的SerializationContext();
私有最终Amf3Output amfout=新Amf3Output(序列化上下文);
@凌驾
受保护对象编码(ChannelHandlerContext arg0、通道arg1、,
对象arg2)引发异常{
te=(T)arg2;
ByteArrayOutputStream byteoutStreamSize=新建ByteArrayOutputStream();
amfout.setOutputStream(字节流大小);
amfout.writeObject(e.getBody());
//byteoutStreamSize在这里变为空的概率很小,在调试模式下,我可以确定e.getBody()有数据
//我认为byteoutStreamSize可能是空的,因为另一个线程调用“amfout.flush()”或“amfout.reset()”
amfout.flush();
//...
amfout.reset();
}
}

调用Channel.write不仅仅是属于netty的工作线程或ExecutionHandler中的线程。有一个由我自己创建的线程池将调用Channel.write()。 在我将amfout&serializationContext的两个变量移动到encode()函数中作为局部变量后,问题就消失了


Doc说ChannelPipeline是线程安全的,我读了netty 3.4.5发现“添加”、“删除”。。。操作已锁定,但sendDownstream和sendUpstream没有锁定。因此,如果存在不属于工作线程池或ExecutionHandler线程池的线程,并且所有这些线程都调用Channel.write(),那么解码器和编码器中会发生并发问题,我认为您正确理解了并发性。您必须:

  • 确保通道处理程序是线程安全的(没有变化的实例变量)
  • 使用ChannelPipelineFactory,以便为每个通道创建新管道

  • 通道管道是线程安全的,但这里的问题是下游事件和上游事件的事件执行模型不同:

    • 默认情况下,使用(多个)用户线程执行下游处理程序

    • 默认情况下,下游处理程序不是线程安全的,因为它们可以由多个用户线程以任何顺序执行(通常
      downstreameEvents
      是轻量级的,因此它们的处理程序不维护实例变量中的状态)。查看Netty代码库中的
      onetooneeCoder
      实现。他们都没有一个国家

    • 默认情况下,上游处理程序使用单个线程执行,或者使用多个线程逐个执行(如果使用了执行处理程序)

    • 上游处理程序是线程安全的,因为执行单线程事件(即使它们可以保持可变状态)

    因此,有人可能会错误地认为下游处理程序和上游处理程序一样是线程安全的

    正如您所说,解决方案是将实例变量移动到局部范围 如果不需要状态。否则,请使下游处理方法线程安全