java - Netty的并发编码

标签 java concurrency netty

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

Channels.pipeline(
    idleHandler,
    new AmfDecoder<GameEvent>(GameEvent.class),
    new AmfEncoder<GameEvent>(),
    concurrencyHandler,
    new 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();
}

}

Channel.write的调用不仅是属于netty的工作线程的线程或者Exeutionhandler中的线程。我自己创建的线程池会调用Channel.write()。 当我将amfout和serializationContext的2个变量移入encode()函数作为局部变量后,问题就消失了。

Doc说ChannelPipeline是线程安全的,我读netty 3.4.5发现“add”,“remove”...操作被锁定,但sendDownstream和sendUpstream没有锁定。因此,如果存在不属于工作线程池或ExecutionHandler线程池的线程,并且所有这些线程都调用Channel.write(),则解码器和编码器中将出现并发问题

最佳答案

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

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

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

  • 上游处理程序默认使用单个线程执行,或者使用多个线程一一执行(如果使用执行处理程序)。

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

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

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

关于java - Netty的并发编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10699688/

相关文章:

java - Swing gui 不显示,但没有错误?

Java并发,在父线程中访问socket

python - 非常简单的Python并发编程

java - Netty 以 100% CPU 运行

java - Http 服务器 - Netty FileRegions 是否可重用?

java - 混帐 : 'Binary Files Differ.' How to solve this issue in gitHub?

java - 使用java测量磁盘写入/读取速度

java - JPA(和继承)如何获得给定父类(super class)的所有实体

Java 并发 : How can I tell which Future belongs to which Callable during processing?

scala - Netty SslHandler 头痛