Tcp Netty:在多个Netty客户之间共享NioClientSocketChannelFactory的正确方式是什么

Tcp Netty:在多个Netty客户之间共享NioClientSocketChannelFactory的正确方式是什么,tcp,netty,jboss5.x,sharing,Tcp,Netty,Jboss5.x,Sharing,我对内蒂不熟悉。我使用的是“Netty 3.6.2.最终版”。我创建了一个Netty客户端(MyClient),它与远程服务器(服务器实现了基于TCP的自定义协议)通信。我为每个MyClient实例(在构造函数中)创建一个新的ClientBootstrap实例。 我的问题是,如果我在MyClient的所有实例中共享“NioClientSocketChannelFactory”工厂对象,那么何时/如何释放与“NioClientSocketChannelFactory”关联的所有资源 换句话说,由于

我对内蒂不熟悉。我使用的是“Netty 3.6.2.最终版”。我创建了一个Netty客户端(MyClient),它与远程服务器(服务器实现了基于TCP的自定义协议)通信。我为每个MyClient实例(在构造函数中)创建一个新的ClientBootstrap实例。 我的问题是,如果我在MyClient的所有实例中共享“NioClientSocketChannelFactory”工厂对象,那么何时/如何释放与“NioClientSocketChannelFactory”关联的所有资源

换句话说,由于我的Netty客户端在一个全天候运行的JBOSS容器中运行,我应该通过调用“bootstrap.releaseExternalResources();”来释放所有资源吗?我应该在何时/何地这样做

更多信息:我的Netty客户端是从JBOSS容器中的两个场景调用的。首先,在无限for循环中,每次传递需要发送到远程服务器的字符串(实际上类似于下面的代码)

另一个场景是在并发线程中调用我的Netty客户端,每个线程都调用“new MyClient().handle(stringToSend);”

我在下面给出了基本代码。这与Netty网站上的TelnetClient示例非常相似

MyClient

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
public class MyClient {
    //Instantiate this only once per application
    private final static Timer timer = new HashedWheelTimer();

    //All below must come from configuration
    private final String host ="127.0.0.1";
    private final int port =9699; 
    private final InetSocketAddress address = new InetSocketAddress(host, port);
    private ClientBootstrap bootstrap;

    //Timeout when the server sends nothing for n seconds.
        static final int READ_TIMEOUT = 5;

        public MyClient(){
            bootstrap = new ClientBootstrap(NioClientSocketFactorySingleton.getInstance());
        }

    public String handle(String messageToSend){
        bootstrap.setOption("connectTimeoutMillis", 20000);
            bootstrap.setOption("tcpNoDelay", true);
            bootstrap.setOption("keepAlive", true);
            bootstrap.setOption("remoteAddress", address);
        bootstrap.setPipelineFactory(new MyClientPipelineFactory(messageToSend,bootstrap,timer));

         // Start the connection attempt.
            ChannelFuture future = bootstrap.connect();

            // Wait until the connection attempt succeeds or fails.
            channel = future.awaitUninterruptibly().getChannel();


            if (!future.isSuccess()) { 
                return null;  
            }

            // Wait until the connection is closed or the connection attempt fails.
            channel.getCloseFuture().awaitUninterruptibly();

            MyClientHandler myClientHandler=(MyClientHandler)channel.getPipeline().getLast();
            String messageReceived=myClientHandler.getMessageReceived();
        return messageReceived;
    }
}
Singleton NioClientSocketChannelFactory

public class NioClientSocketFactorySingleton {
private static NioClientSocketChannelFactory nioClientSocketChannelFactory;

private NioClientSocketFactorySingleton() {
}

public static synchronized NioClientSocketChannelFactory getInstance() {
    if ( nioClientSocketChannelFactory == null) {
        nioClientSocketChannelFactory=new NioClientSocketChannelFactory(
            Executors.newCachedThreadPool(),
            Executors.newCachedThreadPool());
    }
    return  nioClientSocketChannelFactory;
 }

  protected void finalize() throws Throwable {
    try{
    if(nioClientSocketChannelFactory!=null){    
        // Shut down thread pools to exit.
        nioClientSocketChannelFactory.releaseExternalResources();
    } 
    }catch(Exception e){
    //Can't do anything much
    }
  }
} 
MyClientPipelineFactory

public class MyClientPipelineFactory implements ChannelPipelineFactory {

    private String messageToSend;
    private ClientBootstrap bootstrap;
    private Timer timer;
    public MyClientPipelineFactory(){

    }
    public MyClientPipelineFactory(String messageToSend){
        this.messageToSend=messageToSend;
    }

    public MyClientPipelineFactory(String messageToSend,ClientBootstrap bootstrap, Timer timer){
        this.messageToSend=messageToSend;
        this.bootstrap=bootstrap;
        this.timer=timer;
    }

        public ChannelPipeline getPipeline() throws Exception {

            // Create a default pipeline implementation.
            ChannelPipeline pipeline = pipeline();

            // Add the text line codec combination first,
            //pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
            pipeline.addLast("decoder", new StringDecoder());
            pipeline.addLast("encoder", new StringEncoder());

            //Add readtimeout
            pipeline.addLast("timeout", new ReadTimeoutHandler(timer, MyClient.READ_TIMEOUT));

            // and then business logic.
            pipeline.addLast("handler", new MyClientHandler(messageToSend,bootstrap));


            return pipeline;
        }
}
public class MyClientHandler extends SimpleChannelUpstreamHandler { 

    private String messageToSend="";
    private String messageReceived="";


    public MyClientHandler(String messageToSend,ClientBootstrap bootstrap) {
        this.messageToSend=messageToSend;
        this.bootstrap=bootstrap;
    }

    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e){
        e.getChannel().write(messageToSend);
    }

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e){
        messageReceived=e.getMessage().toString();
    //This take the control back to the MyClient
    e.getChannel().close();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
        // Close the connection when an exception is raised.
        e.getChannel().close();

    }


}
MyClientHandler

public class MyClientPipelineFactory implements ChannelPipelineFactory {

    private String messageToSend;
    private ClientBootstrap bootstrap;
    private Timer timer;
    public MyClientPipelineFactory(){

    }
    public MyClientPipelineFactory(String messageToSend){
        this.messageToSend=messageToSend;
    }

    public MyClientPipelineFactory(String messageToSend,ClientBootstrap bootstrap, Timer timer){
        this.messageToSend=messageToSend;
        this.bootstrap=bootstrap;
        this.timer=timer;
    }

        public ChannelPipeline getPipeline() throws Exception {

            // Create a default pipeline implementation.
            ChannelPipeline pipeline = pipeline();

            // Add the text line codec combination first,
            //pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
            pipeline.addLast("decoder", new StringDecoder());
            pipeline.addLast("encoder", new StringEncoder());

            //Add readtimeout
            pipeline.addLast("timeout", new ReadTimeoutHandler(timer, MyClient.READ_TIMEOUT));

            // and then business logic.
            pipeline.addLast("handler", new MyClientHandler(messageToSend,bootstrap));


            return pipeline;
        }
}
public class MyClientHandler extends SimpleChannelUpstreamHandler { 

    private String messageToSend="";
    private String messageReceived="";


    public MyClientHandler(String messageToSend,ClientBootstrap bootstrap) {
        this.messageToSend=messageToSend;
        this.bootstrap=bootstrap;
    }

    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e){
        e.getChannel().write(messageToSend);
    }

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e){
        messageReceived=e.getMessage().toString();
    //This take the control back to the MyClient
    e.getChannel().close();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
        // Close the connection when an exception is raised.
        e.getChannel().close();

    }


}

只有在确定不再需要releaseExternalResources()时,才应该调用它。例如,当应用程序停止或取消部署时,可能会出现这种情况