Resolved issue: NETTY-84 Replace ChannelFactory.getExternalResource() with ChannelFactory.releaseExternalResources()

This commit is contained in:
Trustin Lee 2008-11-28 11:18:21 +00:00
parent 3e09a4ee60
commit 0830444fc8
17 changed files with 80 additions and 139 deletions

View File

@ -103,7 +103,7 @@ import org.jboss.netty.channel.SimpleChannelHandler;
* {@link ClientBootstrap} instances as you want to apply different settings * {@link ClientBootstrap} instances as you want to apply different settings
* for different {@link Channel}s. * for different {@link Channel}s.
* *
* TODO: Show how to shut down a service using ChannelFactoryResource.release(). * TODO: Show how to shut down a service.
* *
* @author The Netty Project (netty-dev@lists.jboss.org) * @author The Netty Project (netty-dev@lists.jboss.org)
* @author Trustin Lee (tlee@redhat.com) * @author Trustin Lee (tlee@redhat.com)

View File

@ -137,7 +137,7 @@ import org.jboss.netty.channel.SimpleChannelHandler;
* {@link ServerBootstrap} instances as you want to apply different settings * {@link ServerBootstrap} instances as you want to apply different settings
* for different {@link Channel}s. * for different {@link Channel}s.
* *
* TODO: Show how to shut down a service using ChannelFactoryResource.release(). * TODO: Show how to shut down a service.
* *
* @author The Netty Project (netty-dev@lists.jboss.org) * @author The Netty Project (netty-dev@lists.jboss.org)
* @author Trustin Lee (tlee@redhat.com) * @author Trustin Lee (tlee@redhat.com)

View File

@ -22,6 +22,8 @@
*/ */
package org.jboss.netty.channel; package org.jboss.netty.channel;
import java.util.concurrent.Executor;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
@ -36,7 +38,17 @@ import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
* is attached to the new {@link Channel}, and starts to handle all associated * is attached to the new {@link Channel}, and starts to handle all associated
* {@link ChannelEvent}s. * {@link ChannelEvent}s.
* *
* TODO: Document how to shut down a service using ChannelFactoryResource. * <h3>Graceful shutdown</h3>
* <p>
* To shut down a network application service which is managed by a factory.
* you should follow the following steps:
* <ol>
* <li>close all channels created by the factory and their child channels, and</li>
* <li>call {@link #releaseExternalResources()}.</li>
* </ol>
* <p>
* For detailed transport-specific information on shutting down a factory,
* please refer to the Javadoc of {@link ChannelFactory}'s subtypes.
* *
* @author The Netty Project (netty-dev@lists.jboss.org) * @author The Netty Project (netty-dev@lists.jboss.org)
* @author Trustin Lee (tlee@redhat.com) * @author Trustin Lee (tlee@redhat.com)
@ -62,12 +74,14 @@ public interface ChannelFactory {
Channel newChannel(ChannelPipeline pipeline); Channel newChannel(ChannelPipeline pipeline);
/** /**
* Returns the external resources that this factory depends on to function. * Releases the external resources that this factory depends on to function.
* Please note that {@link ChannelFactoryResource#release()} can be called * An external resource is a resource that this factory didn't create by
* to release all external resources conveniently when the resources are not * itself. For example, {@link Executor}s that you specified in the factory
* used by this factory or any other part of your application. * constructor are external resources. You can call this method to release
* An unexpected behavior will be resulted in if the returned resources are * all external resources conveniently when the resources are not used by
* released when there's an open channel which is managed by this factory. * this factory or any other part of your application. An unexpected
* behavior will be resulted in if the resources are released when there's
* an open channel which is managed by this factory.
*/ */
ChannelFactoryResource getExternalResource(); void releaseExternalResources();
} }

View File

@ -1,45 +0,0 @@
/*
* JBoss, Home of Professional Open Source
*
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* by the @author tags. See the COPYRIGHT.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.netty.channel;
import java.util.concurrent.ExecutorService;
/**
* The abstract representation of external resources that a
* {@link ChannelFactory} depends on. A user can release the external
* resources such as {@link ExecutorService}s conveniently.
*
* @author The Netty Project (netty-dev@lists.jboss.org)
* @author Trustin Lee (tlee@redhat.com)
*
* @version $Rev$, $Date$
*
* @apiviz.exclude
*/
public interface ChannelFactoryResource {
/**
* Releases this resource.
*/
void release();
}

View File

@ -44,8 +44,8 @@ class DefaultNioSocketChannelConfig extends DefaultSocketChannelConfig
private static final InternalLogger logger = private static final InternalLogger logger =
InternalLoggerFactory.getInstance(DefaultNioSocketChannelConfig.class); InternalLoggerFactory.getInstance(DefaultNioSocketChannelConfig.class);
private volatile int writeBufferHighWaterMark = 256 * 1024; private volatile int writeBufferHighWaterMark = 64 * 1024;
private volatile int writeBufferLowWaterMark = 128 * 1024; private volatile int writeBufferLowWaterMark = 32 * 1024;
private volatile ReceiveBufferSizePredictor predictor = private volatile ReceiveBufferSizePredictor predictor =
new DefaultReceiveBufferSizePredictor(); new DefaultReceiveBufferSizePredictor();
private volatile int writeSpinCount = 16; private volatile int writeSpinCount = 16;

View File

@ -24,18 +24,15 @@ package org.jboss.netty.channel.socket.nio;
import java.nio.channels.Selector; import java.nio.channels.Selector;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactoryExecutorResource;
import org.jboss.netty.channel.ChannelFactoryResource;
import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink; import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.channel.socket.ClientSocketChannelFactory; import org.jboss.netty.channel.socket.ClientSocketChannelFactory;
import org.jboss.netty.channel.socket.SocketChannel; import org.jboss.netty.channel.socket.SocketChannel;
import org.jboss.netty.util.ExecutorShutdownUtil;
/** /**
* A {@link ClientSocketChannelFactory} which creates a client-side NIO-based * A {@link ClientSocketChannelFactory} which creates a client-side NIO-based
@ -62,7 +59,6 @@ import org.jboss.netty.channel.socket.SocketChannel;
* more {@link Channel}s in a non-blocking mode. * more {@link Channel}s in a non-blocking mode.
* *
* <h3>Life cycle of threads and graceful shutdown</h3> * <h3>Life cycle of threads and graceful shutdown</h3>
* TODO: Rewrite this section to recommend a user to call ChannelFactoryResource.release().
* <p> * <p>
* All threads are acquired from the {@link Executor}s which were specified * All threads are acquired from the {@link Executor}s which were specified
* when a {@link NioClientSocketChannelFactory} was created. A boss thread is * when a {@link NioClientSocketChannelFactory} was created. A boss thread is
@ -78,11 +74,8 @@ import org.jboss.netty.channel.socket.SocketChannel;
* following: * following:
* *
* <ol> * <ol>
* <li>close all channels created by the factory,</li> * <li>close all channels created by the factory, and</li>
* <li>call {@link ExecutorService#shutdownNow()} or {@link ExecutorService#shutdown()} * <li>call {@link #releaseExternalResources()}.</li>
* for all executors which were specified to create the factory, and</li>
* <li>call {@link ExecutorService#awaitTermination(long, TimeUnit)}
* until it returns {@code true}.</li>
* </ol> * </ol>
* *
* Please make sure not to shut down the executor until all channels are * Please make sure not to shut down the executor until all channels are
@ -98,7 +91,8 @@ import org.jboss.netty.channel.socket.SocketChannel;
*/ */
public class NioClientSocketChannelFactory implements ClientSocketChannelFactory { public class NioClientSocketChannelFactory implements ClientSocketChannelFactory {
private final ChannelFactoryResource externalResource; private final Executor bossExecutor;
private final Executor workerExecutor;
private final ChannelSink sink; private final ChannelSink sink;
/** /**
@ -142,7 +136,8 @@ public class NioClientSocketChannelFactory implements ClientSocketChannelFactory
"must be a positive integer."); "must be a positive integer.");
} }
externalResource = new ChannelFactoryExecutorResource(bossExecutor, workerExecutor); this.bossExecutor = bossExecutor;
this.workerExecutor = workerExecutor;
sink = new NioClientSocketPipelineSink(bossExecutor, workerExecutor, workerCount); sink = new NioClientSocketPipelineSink(bossExecutor, workerExecutor, workerCount);
} }
@ -150,7 +145,7 @@ public class NioClientSocketChannelFactory implements ClientSocketChannelFactory
return new NioClientSocketChannel(this, pipeline, sink); return new NioClientSocketChannel(this, pipeline, sink);
} }
public ChannelFactoryResource getExternalResource() { public void releaseExternalResources() {
return externalResource; ExecutorShutdownUtil.shutdown(bossExecutor, workerExecutor);
} }
} }

View File

@ -24,18 +24,15 @@ package org.jboss.netty.channel.socket.nio;
import java.nio.channels.Selector; import java.nio.channels.Selector;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactoryExecutorResource;
import org.jboss.netty.channel.ChannelFactoryResource;
import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink; import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.channel.socket.ServerSocketChannel; import org.jboss.netty.channel.socket.ServerSocketChannel;
import org.jboss.netty.channel.socket.ServerSocketChannelFactory; import org.jboss.netty.channel.socket.ServerSocketChannelFactory;
import org.jboss.netty.util.ExecutorShutdownUtil;
/** /**
* A {@link ServerSocketChannelFactory} which creates a server-side NIO-based * A {@link ServerSocketChannelFactory} which creates a server-side NIO-based
@ -64,7 +61,6 @@ import org.jboss.netty.channel.socket.ServerSocketChannelFactory;
* more {@link Channel}s in a non-blocking mode. * more {@link Channel}s in a non-blocking mode.
* *
* <h3>Life cycle of threads and graceful shutdown</h3> * <h3>Life cycle of threads and graceful shutdown</h3>
* TODO: Rewrite this section to recommend a user to call ChannelFactoryResource.release().
* <p> * <p>
* All threads are acquired from the {@link Executor}s which were specified * All threads are acquired from the {@link Executor}s which were specified
* when a {@link NioServerSocketChannelFactory} was created. Boss threads are * when a {@link NioServerSocketChannelFactory} was created. Boss threads are
@ -81,11 +77,8 @@ import org.jboss.netty.channel.socket.ServerSocketChannelFactory;
* *
* <ol> * <ol>
* <li>unbind all channels created by the factory, * <li>unbind all channels created by the factory,
* <li>close all child channels accepted by the unbound channels,</li> * <li>close all child channels accepted by the unbound channels, and</li>
* <li>call {@link ExecutorService#shutdownNow()} or {@link ExecutorService#shutdown()} * <li>call {@link #releaseExternalResources()}.</li>
* for all executors which were specified to create the factory, and</li>
* <li>call {@link ExecutorService#awaitTermination(long, TimeUnit)}
* until it returns {@code true}.</li>
* </ol> * </ol>
* *
* Please make sure not to shut down the executor until all channels are * Please make sure not to shut down the executor until all channels are
@ -102,7 +95,7 @@ import org.jboss.netty.channel.socket.ServerSocketChannelFactory;
public class NioServerSocketChannelFactory implements ServerSocketChannelFactory { public class NioServerSocketChannelFactory implements ServerSocketChannelFactory {
final Executor bossExecutor; final Executor bossExecutor;
private final ChannelFactoryResource externalResource; private final Executor workerExecutor;
private final ChannelSink sink; private final ChannelSink sink;
/** /**
@ -146,7 +139,7 @@ public class NioServerSocketChannelFactory implements ServerSocketChannelFactory
"must be a positive integer."); "must be a positive integer.");
} }
this.bossExecutor = bossExecutor; this.bossExecutor = bossExecutor;
externalResource = new ChannelFactoryExecutorResource(bossExecutor, workerExecutor); this.workerExecutor = workerExecutor;
sink = new NioServerSocketPipelineSink(workerExecutor, workerCount); sink = new NioServerSocketPipelineSink(workerExecutor, workerCount);
} }
@ -154,7 +147,7 @@ public class NioServerSocketChannelFactory implements ServerSocketChannelFactory
return new NioServerSocketChannel(this, pipeline, sink); return new NioServerSocketChannel(this, pipeline, sink);
} }
public ChannelFactoryResource getExternalResource() { public void releaseExternalResources() {
return externalResource; ExecutorShutdownUtil.shutdown(bossExecutor, workerExecutor);
} }
} }

View File

@ -23,16 +23,13 @@
package org.jboss.netty.channel.socket.oio; package org.jboss.netty.channel.socket.oio;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactoryExecutorResource;
import org.jboss.netty.channel.ChannelFactoryResource;
import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.socket.ClientSocketChannelFactory; import org.jboss.netty.channel.socket.ClientSocketChannelFactory;
import org.jboss.netty.channel.socket.SocketChannel; import org.jboss.netty.channel.socket.SocketChannel;
import org.jboss.netty.util.ExecutorShutdownUtil;
/** /**
* A {@link ClientSocketChannelFactory} which creates a client-side blocking * A {@link ClientSocketChannelFactory} which creates a client-side blocking
@ -51,7 +48,6 @@ import org.jboss.netty.channel.socket.SocketChannel;
* traditional blocking I/O thread model. * traditional blocking I/O thread model.
* *
* <h3>Life cycle of threads and graceful shutdown</h3> * <h3>Life cycle of threads and graceful shutdown</h3>
* TODO: Rewrite this section to recommend a user to call ChannelFactoryResource.release().
* <p> * <p>
* Worker threads are acquired from the {@link Executor} which was specified * Worker threads are acquired from the {@link Executor} which was specified
* when a {@link OioClientSocketChannelFactory} was created (i.e. {@code workerExecutor}.) * when a {@link OioClientSocketChannelFactory} was created (i.e. {@code workerExecutor}.)
@ -64,11 +60,8 @@ import org.jboss.netty.channel.socket.SocketChannel;
* you should do the following: * you should do the following:
* *
* <ol> * <ol>
* <li>close all channels created by the factory,</li> * <li>close all channels created by the factory, and</li>
* <li>call {@link ExecutorService#shutdownNow()} for the executor which was * <li>call {@link #releaseExternalResources()}.</li>
* specified to create the factory, and</li>
* <li>call {@link ExecutorService#awaitTermination(long, TimeUnit)}
* until it returns {@code true}.</li>
* </ol> * </ol>
* *
* Please make sure not to shut down the executor until all channels are * Please make sure not to shut down the executor until all channels are
@ -90,7 +83,7 @@ import org.jboss.netty.channel.socket.SocketChannel;
*/ */
public class OioClientSocketChannelFactory implements ClientSocketChannelFactory { public class OioClientSocketChannelFactory implements ClientSocketChannelFactory {
private final ChannelFactoryResource externalResource; private final Executor workerExecutor;
final OioClientSocketPipelineSink sink; final OioClientSocketPipelineSink sink;
/** /**
@ -103,7 +96,7 @@ public class OioClientSocketChannelFactory implements ClientSocketChannelFactory
if (workerExecutor == null) { if (workerExecutor == null) {
throw new NullPointerException("workerExecutor"); throw new NullPointerException("workerExecutor");
} }
externalResource = new ChannelFactoryExecutorResource(workerExecutor); this.workerExecutor = workerExecutor;
sink = new OioClientSocketPipelineSink(workerExecutor); sink = new OioClientSocketPipelineSink(workerExecutor);
} }
@ -111,7 +104,7 @@ public class OioClientSocketChannelFactory implements ClientSocketChannelFactory
return new OioClientSocketChannel(this, pipeline, sink); return new OioClientSocketChannel(this, pipeline, sink);
} }
public ChannelFactoryResource getExternalResource() { public void releaseExternalResources() {
return externalResource; ExecutorShutdownUtil.shutdown(workerExecutor);
} }
} }

View File

@ -28,12 +28,11 @@ import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactoryExecutorResource;
import org.jboss.netty.channel.ChannelFactoryResource;
import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink; import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.channel.socket.ServerSocketChannel; import org.jboss.netty.channel.socket.ServerSocketChannel;
import org.jboss.netty.channel.socket.ServerSocketChannelFactory; import org.jboss.netty.channel.socket.ServerSocketChannelFactory;
import org.jboss.netty.util.ExecutorShutdownUtil;
/** /**
* A {@link ServerSocketChannelFactory} which creates a server-side blocking * A {@link ServerSocketChannelFactory} which creates a server-side blocking
@ -61,7 +60,6 @@ import org.jboss.netty.channel.socket.ServerSocketChannelFactory;
* traditional blocking I/O thread model. * traditional blocking I/O thread model.
* *
* <h3>Life cycle of threads and graceful shutdown</h3> * <h3>Life cycle of threads and graceful shutdown</h3>
* TODO: Rewrite this section to recommend a user to call ChannelFactoryResource.release().
* <p> * <p>
* All threads are acquired from the {@link Executor}s which were specified * All threads are acquired from the {@link Executor}s which were specified
* when a {@link OioServerSocketChannelFactory} was created. Boss threads are * when a {@link OioServerSocketChannelFactory} was created. Boss threads are
@ -103,7 +101,7 @@ import org.jboss.netty.channel.socket.ServerSocketChannelFactory;
public class OioServerSocketChannelFactory implements ServerSocketChannelFactory { public class OioServerSocketChannelFactory implements ServerSocketChannelFactory {
final Executor bossExecutor; final Executor bossExecutor;
private final ChannelFactoryResource externalResource; private final Executor workerExecutor;
private final ChannelSink sink; private final ChannelSink sink;
/** /**
@ -123,7 +121,7 @@ public class OioServerSocketChannelFactory implements ServerSocketChannelFactory
throw new NullPointerException("workerExecutor"); throw new NullPointerException("workerExecutor");
} }
this.bossExecutor = bossExecutor; this.bossExecutor = bossExecutor;
externalResource = new ChannelFactoryExecutorResource(bossExecutor, workerExecutor); this.workerExecutor = workerExecutor;
sink = new OioServerSocketPipelineSink(workerExecutor); sink = new OioServerSocketPipelineSink(workerExecutor);
} }
@ -131,7 +129,7 @@ public class OioServerSocketChannelFactory implements ServerSocketChannelFactory
return new OioServerSocketChannel(this, pipeline, sink); return new OioServerSocketChannel(this, pipeline, sink);
} }
public ChannelFactoryResource getExternalResource() { public void releaseExternalResources() {
return externalResource; ExecutorShutdownUtil.shutdown(bossExecutor, workerExecutor);
} }
} }

View File

@ -69,6 +69,7 @@ public class DiscardClient {
ClientBootstrap bootstrap = new ClientBootstrap(factory); ClientBootstrap bootstrap = new ClientBootstrap(factory);
DiscardClientHandler handler = new DiscardClientHandler(firstMessageSize); DiscardClientHandler handler = new DiscardClientHandler(firstMessageSize);
//bootstrap.getPipeline().addLast("executor", new ExecutionHandler(new MemoryAwareThreadPoolExecutor(16, 0, 0)));
bootstrap.getPipeline().addLast("handler", handler); bootstrap.getPipeline().addLast("handler", handler);
bootstrap.setOption("tcpNoDelay", true); bootstrap.setOption("tcpNoDelay", true);
bootstrap.setOption("keepAlive", true); bootstrap.setOption("keepAlive", true);
@ -80,6 +81,6 @@ public class DiscardClient {
future.getChannel().getCloseFuture().awaitUninterruptibly(); future.getChannel().getCloseFuture().awaitUninterruptibly();
// Shut down thread pools to exit. // Shut down thread pools to exit.
factory.getExternalResource().release(); factory.releaseExternalResources();
} }
} }

View File

@ -87,6 +87,6 @@ public class FactorialClient {
"Factorial of %,d is: %,d", count, handler.getFactorial()); "Factorial of %,d is: %,d", count, handler.getFactorial());
// Shut down all thread pools to exit. // Shut down all thread pools to exit.
factory.getExternalResource().release(); factory.releaseExternalResources();
} }
} }

View File

@ -82,7 +82,7 @@ public class HttpClient {
Channel channel = future.awaitUninterruptibly().getChannel(); Channel channel = future.awaitUninterruptibly().getChannel();
if (!future.isSuccess()) { if (!future.isSuccess()) {
future.getCause().printStackTrace(); future.getCause().printStackTrace();
factory.getExternalResource().release(); factory.releaseExternalResources();
return; return;
} }
@ -95,6 +95,6 @@ public class HttpClient {
channel.getCloseFuture().awaitUninterruptibly(); channel.getCloseFuture().awaitUninterruptibly();
// Shut down executor threads to exit. // Shut down executor threads to exit.
factory.getExternalResource().release(); factory.releaseExternalResources();
} }
} }

View File

@ -78,7 +78,7 @@ public class SecureChatClient {
Channel channel = future.awaitUninterruptibly().getChannel(); Channel channel = future.awaitUninterruptibly().getChannel();
if (!future.isSuccess()) { if (!future.isSuccess()) {
future.getCause().printStackTrace(); future.getCause().printStackTrace();
factory.getExternalResource().release(); factory.releaseExternalResources();
return; return;
} }
@ -103,6 +103,6 @@ public class SecureChatClient {
channel.close().awaitUninterruptibly(); channel.close().awaitUninterruptibly();
// Shut down all thread pools to exit. // Shut down all thread pools to exit.
factory.getExternalResource().release(); factory.releaseExternalResources();
} }
} }

View File

@ -76,7 +76,7 @@ public class TelnetClient {
Channel channel = future.awaitUninterruptibly().getChannel(); Channel channel = future.awaitUninterruptibly().getChannel();
if (!future.isSuccess()) { if (!future.isSuccess()) {
future.getCause().printStackTrace(); future.getCause().printStackTrace();
factory.getExternalResource(); factory.releaseExternalResources();
return; return;
} }
@ -103,6 +103,6 @@ public class TelnetClient {
channel.close().awaitUninterruptibly(); channel.close().awaitUninterruptibly();
// Shut down all thread pools to exit. // Shut down all thread pools to exit.
factory.getExternalResource().release(); factory.releaseExternalResources();
} }
} }

View File

@ -20,49 +20,37 @@
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org. * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/ */
package org.jboss.netty.channel; package org.jboss.netty.util;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
* A {@link ChannelFactoryResource} whose underlying resource is a list of * Shuts down a list of {@link Executor}s. {@link #shutdown(Executor...)} will
* {@link Executor}s. {@link #release()} will shut down all specified * shut down all specified {@link ExecutorService}s immediately and wait for
* {@link ExecutorService}s immediately and wait for their termination. * their termination. An {@link Executor} which is not an {@link ExecutorService}
* An {@link Executor} which is not an {@link ExecutorService} will be ignored. * will be ignored silently.
* *
* @author The Netty Project (netty-dev@lists.jboss.org) * @author The Netty Project (netty-dev@lists.jboss.org)
* @author Trustin Lee (tlee@redhat.com) * @author Trustin Lee (tlee@redhat.com)
* @version $Rev$, $Date$ * @version $Rev$, $Date$
*
* @apiviz.exclude
*/ */
public class ChannelFactoryExecutorResource implements public class ExecutorShutdownUtil {
ChannelFactoryResource {
private final Executor[] executors;
/** /**
* Creates a new instance with the specified executors. * Shuts down the specified executors.
*
* @param executors a list of {@link Executor}s
*/ */
public ChannelFactoryExecutorResource(Executor... executors) { public static void shutdown(Executor... executors) {
if (executors == null) { Executor[] executorsCopy = new Executor[executors.length];
throw new NullPointerException("executors");
}
this.executors = new Executor[executors.length];
for (int i = 0; i < executors.length; i ++) { for (int i = 0; i < executors.length; i ++) {
if (executors[i] == null) { if (executors[i] == null) {
throw new NullPointerException("executors[" + i + "]"); throw new NullPointerException("executors[" + i + "]");
} }
this.executors[i] = executors[i]; executorsCopy[i] = executors[i];
} }
}
public void release() { for (Executor e: executorsCopy) {
for (Executor e: executors) {
if (!(e instanceof ExecutorService)) { if (!(e instanceof ExecutorService)) {
continue; continue;
} }
@ -80,4 +68,8 @@ public class ChannelFactoryExecutorResource implements
} }
} }
} }
private ExecutorShutdownUtil() {
super();
}
} }

View File

@ -85,7 +85,7 @@ public class NioClientSocketShutdownTimeTest {
f.getChannel().close().awaitUninterruptibly(); f.getChannel().close().awaitUninterruptibly();
} finally { } finally {
b.getFactory().getExternalResource().release(); b.getFactory().releaseExternalResources();
try { try {
serverSocket.close(); serverSocket.close();

View File

@ -106,7 +106,7 @@ public class NioServerSocketShutdownTimeTest {
} }
} }
channel.close().awaitUninterruptibly(); channel.close().awaitUninterruptibly();
bootstrap.getFactory().getExternalResource().release(); bootstrap.getFactory().releaseExternalResources();
} }
long shutdownTime = System.currentTimeMillis() - startTime; long shutdownTime = System.currentTimeMillis() - startTime;