2017-09-03 56 views
2

最近,我在我的netty4项目中找到了一些BlockingOperationException。有些人说,当使用sync()方法启动netty的ServerBootstrap时,会导致死锁,因为sync()会调用await()方法,并且在await()中有一个名为“checkDeadLock”的方法。在Netty 4中导致BlockingOperationException的原因是什么?

但我不这么认为。 ServerBootstrap使用名为boosGroup的EventLoopGroup,而Channel使用workerGroup来操作IO,我不认为它们会互相影响,它们有不同的EventExecutor。

而在我的实践中,死锁异常不会出现在Netty启动过程中,其中大部分发生在await writeAndFlush的Channel之后。

分析源代码,checkDeadLock,BlockingOperationException抛出的异常是当前线程和执行程序线程的执行是否相同。

我的项目的代码是打击:

private void channelWrite(T message) { 
    boolean success = true; 
    boolean sent = true; 
    int timeout = 60; 
    try { 
     ChannelFuture cf = cxt.write(message); 
     cxt.flush(); 
     if (sent) { 
      success = cf.await(timeout); 
     } 
     if (cf.isSuccess()) { 
      logger.debug("send success."); 
     } 
     Throwable cause = cf.cause(); 
     if (cause != null) { 
      this.fireError(new PushException(cause)); 
     } 
    } catch (LostConnectException e) { 
     this.fireError(new PushException(e)); 
    } catch (Exception e) { 
     this.fireError(new PushException(e)); 
    } catch (Throwable e) { 
     this.fireError(new PushException("Failed to send message“, e)); 
    } 
    if (!success) { 
     this.fireError(new PushException("Failed to send message")); 
    } 
} 

我知道了Netty官员建议不要使用同步()或等待()方法,但我想知道是什么情况会导致死锁在进程和当前线程和执行程序的执行线程是相同的。

我更改我的项目代码。

private void pushMessage0(T message) { 
    try { 
     ChannelFuture cf = cxt.writeAndFlush(message); 
     cf.addListener(new ChannelFutureListener() { 
      @Override 
      public void operationComplete(ChannelFuture future) throws PushException { 
       if (future.isSuccess()) { 
        logger.debug("send success."); 
       } else { 
        throw new PushException("Failed to send message."); 
       } 
       Throwable cause = future.cause(); 
       if (cause != null) { 
        throw new PushException(cause); 
       } 
      } 
     }); 
    } catch (LostConnectException e) { 
     this.fireError(new PushException(e)); 
    } catch (Exception e) { 
     this.fireError(new PushException(e)); 
    } catch (Throwable e) { 
     this.fireError(new PushException(e)); 
    } 
} 

但是我面临一个新问题,我无法从ChannelHandlerListener获取pushException。

+0

当然,你不能。你甚至在看到它之前就抛弃了自己。涉及'future.cause()'的代码应该在前面的'else'块中,而不是在那里。 – EJP

+0

你的'pushMessage'抛出'pushexception'在异步世界中不起作用,它应该返回一个Future作为操作,或者使用回调来表示状态 – Ferrybig

回答

2

BlockingOperationException将是网状扔,如果你在同一个线程中调用sync*await*FutureEventExecutor使用以及其中Future被绑定到。这通常是由Channel本身使用的EventLoop

相关问题