最近自己写的nio程序持续报错(client-server端借助mina实现)
DefaultExceptionMonitor.exceptionCaught(45) 2011-09-02 09:40:57 | Unexpected exception.
java.nio.channels.ClosedSelectorException
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:66)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:80)
at org.apache.mina.transport.socket.nio.NioProcessor.select(NioProcessor.java:69)
at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.run(AbstractPollingIoProcessor.java:961)
at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:64)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)
at java.lang.Thread.run(Thread.java:595)
通过搜索引擎没有查出问题,但可能的原因是线程阻塞在Selector.select()时,调用了wakeup方法,而此时selector已经关闭
与淘宝大牛 @dennis zhuang 对这个问题做了一次交流,他与我一致认为问题不在mina上,而在于使用错误,导致mina关闭了selector。
因client每发送一次消息都会报一次异常,Dennis 以此推断是我用短连接但没有复用NioSocketConnector造成的,client端发送完消息关闭NioSocketConnector就可能报ClosedSelectorException问题,这涉及mina的内部实现:
当client端关闭connector,mina要关闭NioProcessor线程,此时线程正阻塞在select上,所以先关闭selector,然后唤醒它,mina就会提示selector已经被关闭
此外创建NioSocketConnector代价太大,所以即使用短连接也得考虑复用它,而不是每通信完一次,就将其关闭,这样就可以解决异常问题(复用connector不关闭它),同时还能提高性能。当然最好的是用mina构建client-server的长连接,实现重连机制,通信稳定且性能更优!
评论