我正在使用netty连接和断开连接。但是,当我尝试断开连接时会遇到异常,我无法完全理解是什么原因造成的。
我有一个全球性的:
private ClientBootstrap bootstrap_;
当我尝试连接时,请执行以下操作:
第一次初始化:
ChannelFactory channelFactory = null;
channelFactory = new OioClientSocketChannelFactory(Executors.newCachedThreadPool());
bootstrap_ = new ClientBootstrap(channelFactory);
其次是:
bootstrap_.setPipelineFactory(() -> {
ChannelPipeline pipeline = Channels.pipeline();
// SOME CODE
});
bootstrap_.setOption("remoteAddress", addr);
bootstrap_.setOption("tcpNoDelay", true);
bootstrap_.setOption("keepAlive", true);
bootstrap_.setOption("configureBlocking", false);
bootstrap_.setOption("connectTimeoutMillis", 5000);
并执行:
bootstrap_.connect(addr);
确实返回成功。
关闭所有通道并尝试执行后不久:
bootstrap_.releaseExternalResources();
停止连接,并返回ExecutorUtil.java抛出的IllegalStateException
"An Executor cannot be shut down from the thread " +
"acquired from itself. Please make sure you are " +
"not calling releaseExternalResources() from an " +
"I/O worker thread."
我不知道为什么会抛出这样的异常以及到底是什么导致了这种异常的发生。在此先感谢您的帮助,此问题确实困扰着我。
最佳答案
该错误消息告诉您,您不能从由执行者管理的线程中调用releaseExternalResources,该执行者本身由releaseExternalResources管理。这会导致死锁,因为releaseExternalResources试图关闭执行程序,该执行程序要等到调用releaseExternalResources的线程返回(不能这样做)后才会返回。
我猜想您是从传递给OioClientSocketChannelFactory的执行程序管理的线程中调用releaseExternalResources的,可能是从处理程序中调用的。这行不通。您需要从完全独立的线程中调用它。一种选择是阻塞主应用程序线程,直到您准备关闭时,向应用程序线程发出信号,并在应用程序退出之前让它调用releaseExternalResources。