Shutdown Executor on MultithreadEventLoopGroup shutdown. Fixes #2837

Motivation:

Currently the Executor created by (Nio|Epoll)EventLoopGroup is not correctly shutdown.
This might lead to resource shortages, due to resources not being freed asap.

Modifications:

If (Nio|Epoll)EventLoopGroup create their internal Executor via a constructor
provided `ExecutorServiceFactory` object or via
MultithreadEventLoopGroup.newDefaultExecutorService(...) the ExecutorService.shutdown()
method will be called after (Nio|Epoll)EventLoopGroup is shutdown.

ExecutorService.shutdown() will not be called if the Executor object was passed
to the (Nio|Epoll)EventLoopGroup (that is, it was instantiated outside of Netty).

Result:

Correctly release resources on (Nio|Epoll)EventLoopGroup shutdown.
This commit is contained in:
Jakob Buchgraber 2014-09-09 14:00:17 +02:00 committed by Trustin Lee
parent 3dba1ef8dd
commit b72a05edb4
30 changed files with 164 additions and 145 deletions

View File

@ -32,7 +32,7 @@ public final class DefaultEventExecutor extends SingleThreadEventExecutor {
}
public DefaultEventExecutor(EventExecutorGroup parent) {
this(parent, new DefaultExecutorFactory(DefaultEventExecutor.class).newExecutor(1));
this(parent, new DefaultExecutorServiceFactory(DefaultEventExecutor.class).newExecutorService(1));
}
public DefaultEventExecutor(EventExecutorGroup parent, Executor executor) {

View File

@ -47,11 +47,11 @@ public class DefaultEventExecutorGroup extends MultithreadEventExecutorGroup {
* Create a new instance.
*
* @param nEventExecutors the number of {@link DefaultEventExecutor}s that this group will use.
* @param executorFactory the {@link ExecutorFactory} which produces the {@link Executor} responsible for
* executing the work handled by this {@link EventExecutorGroup}.
* @param executorServiceFactory the {@link ExecutorServiceFactory} which produces the {@link Executor}
* responsible for executing the work handled by this {@link EventExecutorGroup}.
*/
public DefaultEventExecutorGroup(int nEventExecutors, ExecutorFactory executorFactory) {
super(nEventExecutors, executorFactory);
public DefaultEventExecutorGroup(int nEventExecutors, ExecutorServiceFactory executorServiceFactory) {
super(nEventExecutors, executorServiceFactory);
}
@Override

View File

@ -27,13 +27,14 @@ import io.netty.util.internal.logging.InternalLoggerFactory;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.Locale;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicInteger;
/**
* An implementation of an {@link ExecutorFactory} that creates a new {@link ForkJoinPool} on each
* call to {@link #newExecutor(int)}.
* An implementation of an {@link ExecutorServiceFactory} that creates a new {@link ForkJoinPool} on each
* call to {@link #newExecutorService(int)}.
* <p>
* This {@link ExecutorFactory} powers Netty's nio and epoll eventloops by default. Netty moved from managing its
* This {@link ExecutorServiceFactory} powers Netty's nio and epoll eventloops by default. Netty moved from managing its
* own threads and pinning a thread to each eventloop to an {@link Executor}-based approach. That way advanced
* users of Netty can plug in their own threadpools and gain more control of scheduling the eventloops.
* <p>
@ -43,10 +44,10 @@ import java.util.concurrent.atomic.AtomicInteger;
* The whole discussion can be found on GitHub
* <a href="https://github.com/netty/netty/issues/2250">https://github.com/netty/netty/issues/2250</a>.
*/
public final class DefaultExecutorFactory implements ExecutorFactory {
public final class DefaultExecutorServiceFactory implements ExecutorServiceFactory {
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(DefaultExecutorFactory.class);
InternalLoggerFactory.getInstance(DefaultExecutorServiceFactory.class);
private static final AtomicInteger executorId = new AtomicInteger();
private final String namePrefix;
@ -55,19 +56,19 @@ public final class DefaultExecutorFactory implements ExecutorFactory {
* @param clazzNamePrefix the name of the class will be used to prefix the name of each
* {@link ForkJoinWorkerThread} with.
*/
public DefaultExecutorFactory(Class<?> clazzNamePrefix) {
public DefaultExecutorServiceFactory(Class<?> clazzNamePrefix) {
this(toName(clazzNamePrefix));
}
/**
* @param namePrefix the string to prefix the name of each {@link ForkJoinWorkerThread} with.
*/
public DefaultExecutorFactory(String namePrefix) {
public DefaultExecutorServiceFactory(String namePrefix) {
this.namePrefix = namePrefix;
}
@Override
public Executor newExecutor(int parallelism) {
public ExecutorService newExecutorService(int parallelism) {
ForkJoinWorkerThreadFactory threadFactory =
new DefaultForkJoinWorkerThreadFactory(namePrefix + '-' + executorId.getAndIncrement());

View File

@ -16,12 +16,12 @@
package io.netty.util.concurrent;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
/**
* An object that creates new {@link Executor}s on demand. Using executor factories mainly
* simplifies providing custom executor implementations to Netty's event loops.
* An object that creates new {@link ExecutorService} on demand. Using an {@link ExecutorServiceFactory} mainly
* simplifies providing a custom {@link ExecutorService} implementation to Netty's event loops.
*/
public interface ExecutorFactory {
Executor newExecutor(int parallelism);
public interface ExecutorServiceFactory {
ExecutorService newExecutorService(int parallelism);
}

View File

@ -31,7 +31,7 @@ import java.util.Set;
* table, and it is useful when accessed frequently.
* </p><p>
* To take advantage of this thread-local variable, your thread must implement {@link FastThreadLocalAccess}.
* By default, all threads created by {@link DefaultThreadFactory} and {@link DefaultExecutorFactory} implement
* By default, all threads created by {@link DefaultThreadFactory} and {@link DefaultExecutorServiceFactory} implement
* {@link FastThreadLocalAccess}.
* </p><p>
* Note that the fast path is only possible on threads that implement {@link FastThreadLocalAccess}, because it

View File

@ -19,6 +19,7 @@ import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@ -36,35 +37,49 @@ public abstract class MultithreadEventExecutorGroup extends AbstractEventExecuto
private final EventExecutorChooser chooser;
/**
* @param nEventExecutors the number of {@link EventExecutor}s that will be used by this instance.
* If {@code executor} is {@code null} this number will also be the parallelism
* requested from the default executor. It is generally advised for the number
* of {@link EventExecutor}s and the number of {@link Thread}s used by the
* {@code executor} to lie very close together.
* @param executorFactory the {@link ExecutorFactory} to use, or {@code null} if the default should be used.
* @param args arguments which will passed to each {@link #newChild(Executor, Object...)} call
* @param nEventExecutors the number of {@link EventExecutor}s that will be used by this instance.
* If {@code executor} is {@code null} this number will also be the parallelism
* requested from the default executor. It is generally advised for the number
* of {@link EventExecutor}s and the number of {@link Thread}s used by the
* {@code executor} to lie very close together.
* @param executorServiceFactory the {@link ExecutorServiceFactory} to use, or {@code null} if the default
* should be used.
* @param args arguments which will passed to each {@link #newChild(Executor, Object...)} call.
*/
protected MultithreadEventExecutorGroup(int nEventExecutors, ExecutorFactory executorFactory, Object... args) {
this(nEventExecutors, executorFactory == null ? null : executorFactory.newExecutor(nEventExecutors), args);
protected MultithreadEventExecutorGroup(int nEventExecutors,
ExecutorServiceFactory executorServiceFactory,
Object... args) {
this(nEventExecutors, executorServiceFactory != null
? executorServiceFactory.newExecutorService(nEventExecutors)
: null,
true, args);
}
/**
* @param nEventExecutors the number of {@link EventExecutor}s that will be used by this instance.
* If {@code executor} is {@code null} this number will also be the parallelism
* requested from the default executor. It is generally advised for the number
* of {@link EventExecutor}s and the number of {@link Thread}s used by the
* {@code executor} to lie very close together.
* @param executor the {@link Executor} to use, or {@code null} if the default should be used.
* @param args arguments which will passed to each {@link #newChild(Executor, Object...)} call
* If {@code executor} is {@code null} this number will also be the parallelism
* requested from the default executor. It is generally advised for the number
* of {@link EventExecutor}s and the number of {@link Thread}s used by the
* {@code executor} to lie very close together.
* @param executor the {@link Executor} to use, or {@code null} if the default should be used.
* @param args arguments which will passed to each {@link #newChild(Executor, Object...)} call
*/
protected MultithreadEventExecutorGroup(int nEventExecutors, Executor executor, Object... args) {
this(nEventExecutors, executor, false, args);
}
private MultithreadEventExecutorGroup(int nEventExecutors,
Executor executor,
boolean shutdownExecutor,
Object... args) {
if (nEventExecutors <= 0) {
throw new IllegalArgumentException(
String.format("nEventExecutors: %d (expected: > 0)", nEventExecutors));
}
if (executor == null) {
executor = newDefaultExecutor(nEventExecutors);
executor = newDefaultExecutorService(nEventExecutors);
shutdownExecutor = true;
}
children = new EventExecutor[nEventExecutors];
@ -104,11 +119,18 @@ public abstract class MultithreadEventExecutorGroup extends AbstractEventExecuto
}
}
final boolean shutdownExecutor0 = shutdownExecutor;
final Executor executor0 = executor;
final FutureListener<Object> terminationListener = new FutureListener<Object>() {
@Override
public void operationComplete(Future<Object> future) throws Exception {
if (terminatedChildren.incrementAndGet() == children.length) {
terminationFuture.setSuccess(null);
if (shutdownExecutor0) {
// This cast is correct because shutdownExecutor0 is only try if
// executor0 is of type ExecutorService.
((ExecutorService) executor0).shutdown();
}
}
}
};
@ -122,8 +144,8 @@ public abstract class MultithreadEventExecutorGroup extends AbstractEventExecuto
readonlyChildren = Collections.unmodifiableSet(childrenSet);
}
protected Executor newDefaultExecutor(int nEventExecutors) {
return new DefaultExecutorFactory(getClass()).newExecutor(nEventExecutors);
protected ExecutorService newDefaultExecutorService(int nEventExecutors) {
return new DefaultExecutorServiceFactory(getClass()).newExecutorService(nEventExecutors);
}
@Override

View File

@ -177,7 +177,7 @@ public class DefaultPromiseTest {
private static final class TestEventExecutor extends SingleThreadEventExecutor {
TestEventExecutor() {
super(null, new DefaultExecutorFactory(TestEventExecutor.class).newExecutor(1), true);
super(null, new DefaultExecutorServiceFactory(TestEventExecutor.class).newExecutorService(1), true);
}
@Override

View File

@ -79,15 +79,15 @@ public class FastThreadLocalTest {
}
/**
* Make sure threads created by the {@link DefaultExecutorFactory} and {@link DefaultThreadFactory}
* Make sure threads created by the {@link DefaultExecutorServiceFactory} and {@link DefaultThreadFactory}
* implement the {@link FastThreadLocalAccess} interface.
*/
@Test
public void testIsFastThreadLocalThread() {
ExecutorFactory executorFactory = new DefaultExecutorFactory(FastThreadLocalTest.class);
ExecutorServiceFactory executorServiceFactory = new DefaultExecutorServiceFactory(FastThreadLocalTest.class);
int parallelism = Runtime.getRuntime().availableProcessors() * 2;
Executor executor = executorFactory.newExecutor(parallelism);
Executor executor = executorServiceFactory.newExecutorService(parallelism);
// submit a "high" number of tasks, to get a good chance to touch every thread.
for (int i = 0; i < parallelism * 100; i++) {
executor.execute(new Runnable() {

View File

@ -23,8 +23,8 @@ import io.netty.channel.udt.UdtChannel;
import io.netty.channel.udt.nio.NioUdtProvider;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.concurrent.DefaultExecutorFactory;
import io.netty.util.concurrent.ExecutorFactory;
import io.netty.util.concurrent.DefaultExecutorServiceFactory;
import io.netty.util.concurrent.ExecutorServiceFactory;
/**
* UDT Byte Stream Client
@ -42,7 +42,7 @@ public final class ByteEchoClient {
public static void main(String[] args) throws Exception {
// Configure the client.
final ExecutorFactory connectFactory = new DefaultExecutorFactory("connect");
final ExecutorServiceFactory connectFactory = new DefaultExecutorServiceFactory("connect");
final NioEventLoopGroup connectGroup =
new NioEventLoopGroup(1, connectFactory, NioUdtProvider.BYTE_PROVIDER);

View File

@ -24,8 +24,8 @@ import io.netty.channel.udt.UdtChannel;
import io.netty.channel.udt.nio.NioUdtProvider;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.concurrent.DefaultExecutorFactory;
import io.netty.util.concurrent.ExecutorFactory;
import io.netty.util.concurrent.DefaultExecutorServiceFactory;
import io.netty.util.concurrent.ExecutorServiceFactory;
/**
* UDT Byte Stream Server
@ -37,8 +37,8 @@ public final class ByteEchoServer {
static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));
public static void main(String[] args) throws Exception {
ExecutorFactory acceptFactory = new DefaultExecutorFactory("accept");
ExecutorFactory connectFactory = new DefaultExecutorFactory("connect");
ExecutorServiceFactory acceptFactory = new DefaultExecutorServiceFactory("accept");
ExecutorServiceFactory connectFactory = new DefaultExecutorServiceFactory("connect");
NioEventLoopGroup acceptGroup = new NioEventLoopGroup(1, acceptFactory, NioUdtProvider.BYTE_PROVIDER);
NioEventLoopGroup connectGroup = new NioEventLoopGroup(1, connectFactory, NioUdtProvider.BYTE_PROVIDER);

View File

@ -23,8 +23,8 @@ import io.netty.channel.udt.UdtChannel;
import io.netty.channel.udt.nio.NioUdtProvider;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.concurrent.DefaultExecutorFactory;
import io.netty.util.concurrent.ExecutorFactory;
import io.netty.util.concurrent.DefaultExecutorServiceFactory;
import io.netty.util.concurrent.ExecutorServiceFactory;
import java.util.logging.Logger;
@ -46,7 +46,7 @@ public final class MsgEchoClient {
public static void main(String[] args) throws Exception {
// Configure the client.
final ExecutorFactory connectFactory = new DefaultExecutorFactory("connect");
final ExecutorServiceFactory connectFactory = new DefaultExecutorServiceFactory("connect");
final NioEventLoopGroup connectGroup =
new NioEventLoopGroup(1, connectFactory, NioUdtProvider.MESSAGE_PROVIDER);

View File

@ -24,8 +24,8 @@ import io.netty.channel.udt.UdtChannel;
import io.netty.channel.udt.nio.NioUdtProvider;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.concurrent.DefaultExecutorFactory;
import io.netty.util.concurrent.ExecutorFactory;
import io.netty.util.concurrent.DefaultExecutorServiceFactory;
import io.netty.util.concurrent.ExecutorServiceFactory;
/**
* UDT Message Flow Server
@ -37,8 +37,8 @@ public final class MsgEchoServer {
static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));
public static void main(String[] args) throws Exception {
final ExecutorFactory acceptFactory = new DefaultExecutorFactory("accept");
final ExecutorFactory connectFactory = new DefaultExecutorFactory("connect");
final ExecutorServiceFactory acceptFactory = new DefaultExecutorServiceFactory("accept");
final ExecutorServiceFactory connectFactory = new DefaultExecutorServiceFactory("connect");
final NioEventLoopGroup acceptGroup =
new NioEventLoopGroup(1, acceptFactory, NioUdtProvider.MESSAGE_PROVIDER);
final NioEventLoopGroup connectGroup =

View File

@ -23,8 +23,8 @@ import io.netty.channel.udt.UdtChannel;
import io.netty.channel.udt.nio.NioUdtProvider;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.concurrent.DefaultExecutorFactory;
import io.netty.util.concurrent.ExecutorFactory;
import io.netty.util.concurrent.DefaultExecutorServiceFactory;
import io.netty.util.concurrent.ExecutorServiceFactory;
import java.net.InetSocketAddress;
@ -48,7 +48,7 @@ public abstract class MsgEchoPeerBase {
public void run() throws Exception {
// Configure the peer.
final ExecutorFactory connectFactory = new DefaultExecutorFactory("rendezvous");
final ExecutorServiceFactory connectFactory = new DefaultExecutorServiceFactory("rendezvous");
final NioEventLoopGroup connectGroup =
new NioEventLoopGroup(1, connectFactory, NioUdtProvider.MESSAGE_PROVIDER);

View File

@ -23,8 +23,8 @@ import io.netty.channel.udt.UdtChannel;
import io.netty.channel.udt.nio.NioUdtProvider;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.concurrent.DefaultExecutorFactory;
import io.netty.util.concurrent.ExecutorFactory;
import io.netty.util.concurrent.DefaultExecutorServiceFactory;
import io.netty.util.concurrent.ExecutorServiceFactory;
import java.net.SocketAddress;
@ -50,7 +50,7 @@ public class ByteEchoPeerBase {
}
public void run() throws Exception {
final ExecutorFactory connectFactory = new DefaultExecutorFactory("rendezvous");
final ExecutorServiceFactory connectFactory = new DefaultExecutorServiceFactory("rendezvous");
final NioEventLoopGroup connectGroup =
new NioEventLoopGroup(1, connectFactory, NioUdtProvider.BYTE_PROVIDER);

View File

@ -27,7 +27,7 @@ import io.netty.channel.sctp.oio.OioSctpServerChannel;
import io.netty.testsuite.util.TestUtils;
import io.netty.testsuite.transport.TestsuitePermutation.BootstrapComboFactory;
import io.netty.testsuite.transport.TestsuitePermutation.BootstrapFactory;
import io.netty.util.concurrent.DefaultExecutorFactory;
import io.netty.util.concurrent.DefaultExecutorServiceFactory;
import io.netty.util.concurrent.DefaultThreadFactory;
import java.util.ArrayList;
@ -39,9 +39,9 @@ public final class SctpTestPermutation {
private static final int BOSSES = 2;
private static final int WORKERS = 3;
private static final EventLoopGroup nioBossGroup =
new NioEventLoopGroup(BOSSES, new DefaultExecutorFactory("testsuite-sctp-nio-boss"));
new NioEventLoopGroup(BOSSES, new DefaultExecutorServiceFactory("testsuite-sctp-nio-boss"));
private static final EventLoopGroup nioWorkerGroup =
new NioEventLoopGroup(WORKERS, new DefaultExecutorFactory("testsuite-sctp-nio-worker"));
new NioEventLoopGroup(WORKERS, new DefaultExecutorServiceFactory("testsuite-sctp-nio-worker"));
private static final EventLoopGroup oioBossGroup =
new OioEventLoopGroup(Integer.MAX_VALUE, new DefaultThreadFactory("testsuite-sctp-oio-boss", true));
private static final EventLoopGroup oioWorkerGroup =

View File

@ -33,7 +33,7 @@ import io.netty.channel.socket.oio.OioServerSocketChannel;
import io.netty.channel.socket.oio.OioSocketChannel;
import io.netty.testsuite.transport.TestsuitePermutation.BootstrapComboFactory;
import io.netty.testsuite.transport.TestsuitePermutation.BootstrapFactory;
import io.netty.util.concurrent.DefaultExecutorFactory;
import io.netty.util.concurrent.DefaultExecutorServiceFactory;
import io.netty.util.concurrent.DefaultThreadFactory;
import java.util.ArrayList;
@ -50,9 +50,9 @@ public class SocketTestPermutation {
protected static final int OIO_SO_TIMEOUT = 10; // Use short timeout for faster runs.
protected final EventLoopGroup nioBossGroup =
new NioEventLoopGroup(BOSSES, new DefaultExecutorFactory("testsuite-nio-boss"));
new NioEventLoopGroup(BOSSES, new DefaultExecutorServiceFactory("testsuite-nio-boss"));
protected final EventLoopGroup nioWorkerGroup =
new NioEventLoopGroup(WORKERS, new DefaultExecutorFactory("testsuite-nio-worker"));
new NioEventLoopGroup(WORKERS, new DefaultExecutorServiceFactory("testsuite-nio-worker"));
protected final EventLoopGroup oioBossGroup =
new OioEventLoopGroup(Integer.MAX_VALUE, new DefaultThreadFactory("testsuite-oio-boss", true));
protected final EventLoopGroup oioWorkerGroup =

View File

@ -32,8 +32,8 @@ import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;
import io.netty.util.concurrent.DefaultExecutorFactory;
import io.netty.util.concurrent.ExecutorFactory;
import io.netty.util.concurrent.DefaultExecutorServiceFactory;
import io.netty.util.concurrent.ExecutorServiceFactory;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.junit.Test;
import org.slf4j.Logger;
@ -65,7 +65,7 @@ public class UDTClientServerConnectionTest {
@Override
public void run() {
final Bootstrap boot = new Bootstrap();
final ExecutorFactory clientFactory = new DefaultExecutorFactory("client");
final ExecutorServiceFactory clientFactory = new DefaultExecutorServiceFactory("client");
final NioEventLoopGroup connectGroup =
new NioEventLoopGroup(1, clientFactory, NioUdtProvider.BYTE_PROVIDER);
@ -193,8 +193,8 @@ public class UDTClientServerConnectionTest {
@Override
public void run() {
final ServerBootstrap boot = new ServerBootstrap();
final ExecutorFactory acceptFactory = new DefaultExecutorFactory("accept");
final ExecutorFactory serverFactory = new DefaultExecutorFactory("server");
final ExecutorServiceFactory acceptFactory = new DefaultExecutorServiceFactory("accept");
final ExecutorServiceFactory serverFactory = new DefaultExecutorServiceFactory("server");
final NioEventLoopGroup acceptGroup =
new NioEventLoopGroup(1, acceptFactory, NioUdtProvider.BYTE_PROVIDER);
final NioEventLoopGroup connectGroup =

View File

@ -19,10 +19,9 @@ import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.MultithreadEventLoopGroup;
import io.netty.util.concurrent.EventExecutor;
import io.netty.util.concurrent.ExecutorFactory;
import io.netty.util.concurrent.ExecutorServiceFactory;
import java.util.concurrent.Executor;
import io.netty.util.concurrent.DefaultExecutorFactory;
/**
@ -35,7 +34,7 @@ public final class EpollEventLoopGroup extends MultithreadEventLoopGroup {
* Create a new instance that uses twice as many {@link EventLoop}s as there processors/cores
* available, as well as the default {@link Executor}.
*
* @see DefaultExecutorFactory
* @see io.netty.util.concurrent.DefaultExecutorServiceFactory
*/
public EpollEventLoopGroup() {
this(0);
@ -44,7 +43,7 @@ public final class EpollEventLoopGroup extends MultithreadEventLoopGroup {
/**
* Create a new instance that uses the default {@link Executor}.
*
* @see DefaultExecutorFactory
* @see io.netty.util.concurrent.DefaultExecutorServiceFactory
*
* @param nEventLoops the number of {@link EventLoop}s that will be used by this instance.
* If {@code executor} is {@code null} this number will also be the parallelism
@ -73,10 +72,11 @@ public final class EpollEventLoopGroup extends MultithreadEventLoopGroup {
* requested from the default executor. It is generally advised for the number
* of {@link EventLoop}s and the number of {@link Thread}s used by the
* {@code executor} to lie very close together.
* @param executorFactory the {@link ExecutorFactory} to use, or {@code null} if the default should be used.
* @param executorServiceFactory the {@link ExecutorServiceFactory} to use, or {@code null} if the
* default should be used.
*/
public EpollEventLoopGroup(int nEventLoops, ExecutorFactory executorFactory) {
this(nEventLoops, executorFactory, 128);
public EpollEventLoopGroup(int nEventLoops, ExecutorServiceFactory executorServiceFactory) {
this(nEventLoops, executorServiceFactory, 128);
}
/**
@ -98,11 +98,12 @@ public final class EpollEventLoopGroup extends MultithreadEventLoopGroup {
* requested from the default executor. It is generally advised for the number
* of {@link EventLoop}s and the number of {@link Thread}s used by the
* {@code executor} to lie very close together.
* @param executorFactory the {@link ExecutorFactory} to use, or {@code null} if the default should be used.
* @param executorServiceFactory the {@link ExecutorServiceFactory} to use, or {@code null} if the default
* should be used.
* @param maxEventsAtOnce the maximum number of epoll events to handle per epollWait(...).
*/
public EpollEventLoopGroup(int nEventLoops, ExecutorFactory executorFactory, int maxEventsAtOnce) {
super(nEventLoops, executorFactory, maxEventsAtOnce);
public EpollEventLoopGroup(int nEventLoops, ExecutorServiceFactory executorServiceFactory, int maxEventsAtOnce) {
super(nEventLoops, executorServiceFactory, maxEventsAtOnce);
}
/**

View File

@ -27,7 +27,7 @@ import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.TestsuitePermutation.BootstrapFactory;
import io.netty.testsuite.transport.socket.SocketTestPermutation;
import io.netty.util.concurrent.DefaultExecutorFactory;
import io.netty.util.concurrent.DefaultExecutorServiceFactory;
import java.util.Arrays;
import java.util.List;
@ -37,9 +37,9 @@ class EpollSocketTestPermutation extends SocketTestPermutation {
static final SocketTestPermutation INSTANCE = new EpollSocketTestPermutation();
static final EventLoopGroup EPOLL_BOSS_GROUP =
new EpollEventLoopGroup(BOSSES, new DefaultExecutorFactory("testsuite-epoll-boss"));
new EpollEventLoopGroup(BOSSES, new DefaultExecutorServiceFactory("testsuite-epoll-boss"));
static final EventLoopGroup EPOLL_WORKER_GROUP =
new EpollEventLoopGroup(WORKERS, new DefaultExecutorFactory("testsuite-epoll-worker"));
new EpollEventLoopGroup(WORKERS, new DefaultExecutorServiceFactory("testsuite-epoll-worker"));
@Override
public List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> socket() {

View File

@ -28,7 +28,7 @@ import io.netty.test.udt.util.CustomReporter;
import io.netty.test.udt.util.EchoMessageHandler;
import io.netty.test.udt.util.TrafficControl;
import io.netty.test.udt.util.UnitHelp;
import io.netty.util.concurrent.DefaultExecutorFactory;
import io.netty.util.concurrent.DefaultExecutorServiceFactory;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
@ -93,9 +93,9 @@ public final class UdtNetty {
final ChannelHandler handler2 = new EchoMessageHandler(null, size);
final NioEventLoopGroup group1 =
new NioEventLoopGroup(1, new DefaultExecutorFactory("group1"), NioUdtProvider.MESSAGE_PROVIDER);
new NioEventLoopGroup(1, new DefaultExecutorServiceFactory("group1"), NioUdtProvider.MESSAGE_PROVIDER);
final NioEventLoopGroup group2 =
new NioEventLoopGroup(1, new DefaultExecutorFactory("group2"), NioUdtProvider.MESSAGE_PROVIDER);
new NioEventLoopGroup(1, new DefaultExecutorServiceFactory("group2"), NioUdtProvider.MESSAGE_PROVIDER);
final Bootstrap peerBoot1 = new Bootstrap();
peerBoot1.group(group1)

View File

@ -25,7 +25,7 @@ import io.netty.channel.udt.nio.NioUdtByteRendezvousChannel;
import io.netty.channel.udt.nio.NioUdtProvider;
import io.netty.test.udt.util.EchoByteHandler;
import io.netty.test.udt.util.UnitHelp;
import io.netty.util.concurrent.DefaultExecutorFactory;
import io.netty.util.concurrent.DefaultExecutorServiceFactory;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import org.junit.Test;
@ -71,9 +71,9 @@ public class NioUdtByteRendezvousChannelTest extends AbstractUdtTest {
final EchoByteHandler handler2 = new EchoByteHandler(rate2, messageSize);
final NioEventLoopGroup group1 =
new NioEventLoopGroup(1, new DefaultExecutorFactory("group1"), NioUdtProvider.BYTE_PROVIDER);
new NioEventLoopGroup(1, new DefaultExecutorServiceFactory("group1"), NioUdtProvider.BYTE_PROVIDER);
final NioEventLoopGroup group2 =
new NioEventLoopGroup(1, new DefaultExecutorFactory("group2"), NioUdtProvider.BYTE_PROVIDER);
new NioEventLoopGroup(1, new DefaultExecutorServiceFactory("group2"), NioUdtProvider.BYTE_PROVIDER);
final Bootstrap boot1 = new Bootstrap();
boot1.group(group1)

View File

@ -25,7 +25,7 @@ import io.netty.channel.udt.nio.NioUdtMessageRendezvousChannel;
import io.netty.channel.udt.nio.NioUdtProvider;
import io.netty.test.udt.util.EchoMessageHandler;
import io.netty.test.udt.util.UnitHelp;
import io.netty.util.concurrent.DefaultExecutorFactory;
import io.netty.util.concurrent.DefaultExecutorServiceFactory;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import org.junit.Test;
@ -69,9 +69,9 @@ public class NioUdtMessageRendezvousChannelTest extends AbstractUdtTest {
final EchoMessageHandler handler2 = new EchoMessageHandler(rate2, messageSize);
final NioEventLoopGroup group1 =
new NioEventLoopGroup(1, new DefaultExecutorFactory("group1"), NioUdtProvider.MESSAGE_PROVIDER);
new NioEventLoopGroup(1, new DefaultExecutorServiceFactory("group1"), NioUdtProvider.MESSAGE_PROVIDER);
final NioEventLoopGroup group2 =
new NioEventLoopGroup(1, new DefaultExecutorFactory("group2"), NioUdtProvider.MESSAGE_PROVIDER);
new NioEventLoopGroup(1, new DefaultExecutorServiceFactory("group2"), NioUdtProvider.MESSAGE_PROVIDER);
final Bootstrap boot1 = new Bootstrap();
boot1.group(group1)

View File

@ -15,7 +15,7 @@
*/
package io.netty.channel;
import io.netty.util.concurrent.DefaultExecutorFactory;
import io.netty.util.concurrent.DefaultExecutorServiceFactory;
import java.util.concurrent.Executor;
public class DefaultEventLoop extends SingleThreadEventLoop {
@ -29,7 +29,7 @@ public class DefaultEventLoop extends SingleThreadEventLoop {
}
public DefaultEventLoop(EventLoopGroup parent) {
this(parent, new DefaultExecutorFactory(DefaultEventLoop.class).newExecutor(1));
this(parent, new DefaultExecutorServiceFactory(DefaultEventLoop.class).newExecutorService(1));
}
public DefaultEventLoop(EventLoopGroup parent, Executor executor) {

View File

@ -15,7 +15,7 @@
*/
package io.netty.channel;
import io.netty.util.concurrent.ExecutorFactory;
import io.netty.util.concurrent.ExecutorServiceFactory;
import java.util.concurrent.Executor;
@ -28,7 +28,7 @@ public class DefaultEventLoopGroup extends MultithreadEventLoopGroup {
* Create a new instance that uses twice as many {@link EventLoop}s as there processors/cores
* available, as well as the default {@link Executor}.
*
* @see io.netty.util.concurrent.DefaultExecutorFactory
* @see io.netty.util.concurrent.DefaultExecutorServiceFactory
*/
public DefaultEventLoopGroup() {
this(0);
@ -63,10 +63,11 @@ public class DefaultEventLoopGroup extends MultithreadEventLoopGroup {
* requested from the default executor. It is generally advised for the number
* of {@link EventLoop}s and the number of {@link Thread}s used by the
* {@code executor} to lie very close together.
* @param executorFactory the {@link ExecutorFactory} to use, or {@code null} if the default should be used.
* @param executorServiceFactory the {@link ExecutorServiceFactory} to use, or {@code null} if the default
* should be used.
*/
public DefaultEventLoopGroup(int nEventLoops, ExecutorFactory executorFactory) {
super(nEventLoops, executorFactory);
public DefaultEventLoopGroup(int nEventLoops, ExecutorServiceFactory executorServiceFactory) {
super(nEventLoops, executorServiceFactory);
}
@Override

View File

@ -15,7 +15,7 @@
*/
package io.netty.channel;
import io.netty.util.concurrent.ExecutorFactory;
import io.netty.util.concurrent.ExecutorServiceFactory;
import io.netty.util.concurrent.MultithreadEventExecutorGroup;
import io.netty.util.internal.SystemPropertyUtil;
import io.netty.util.internal.logging.InternalLogger;
@ -50,10 +50,12 @@ public abstract class MultithreadEventLoopGroup extends MultithreadEventExecutor
}
/**
* @see {@link MultithreadEventExecutorGroup#MultithreadEventExecutorGroup(int, ExecutorFactory, Object...)}
* @see {@link MultithreadEventExecutorGroup#MultithreadEventExecutorGroup(int, ExecutorServiceFactory, Object...)}
*/
protected MultithreadEventLoopGroup(int nEventLoops, ExecutorFactory executorFactory, Object... args) {
super(nEventLoops == 0 ? DEFAULT_EVENT_LOOP_THREADS : nEventLoops, executorFactory, args);
protected MultithreadEventLoopGroup(int nEventLoops,
ExecutorServiceFactory executorServiceFactory,
Object... args) {
super(nEventLoops == 0 ? DEFAULT_EVENT_LOOP_THREADS : nEventLoops, executorServiceFactory, args);
}
@Override

View File

@ -18,9 +18,8 @@ package io.netty.channel.nio;
import io.netty.channel.Channel;
import io.netty.channel.EventLoop;
import io.netty.channel.MultithreadEventLoopGroup;
import io.netty.util.concurrent.DefaultExecutorFactory;
import io.netty.util.concurrent.EventExecutor;
import io.netty.util.concurrent.ExecutorFactory;
import io.netty.util.concurrent.ExecutorServiceFactory;
import java.nio.channels.Selector;
import java.nio.channels.spi.SelectorProvider;
@ -36,7 +35,7 @@ public class NioEventLoopGroup extends MultithreadEventLoopGroup {
* available, as well as the default {@link Executor} and the {@link SelectorProvider} which
* is returned by {@link SelectorProvider#provider()}.
*
* @see DefaultExecutorFactory
* @see io.netty.util.concurrent.DefaultExecutorServiceFactory
*/
public NioEventLoopGroup() {
this(0);
@ -46,7 +45,7 @@ public class NioEventLoopGroup extends MultithreadEventLoopGroup {
* Create a new instance that uses the default {@link Executor} and the {@link SelectorProvider} which
* is returned by {@link SelectorProvider#provider()}.
*
* @see DefaultExecutorFactory
* @see io.netty.util.concurrent.DefaultExecutorServiceFactory
*
* @param nEventLoops the number of {@link EventLoop}s that will be used by this instance.
* If {@code executor} is {@code null} this number will also be the parallelism
@ -81,10 +80,11 @@ public class NioEventLoopGroup extends MultithreadEventLoopGroup {
* requested from the default executor. It is generally advised for the number
* of {@link EventLoop}s and the number of {@link Thread}s used by the
* {@code executor} to lie very close together.
* @param executorFactory the {@link ExecutorFactory} to use, or {@code null} if the default should be used.
* @param executorServiceFactory the {@link ExecutorServiceFactory} to use, or {@code null} if the default
* should be used.
*/
public NioEventLoopGroup(int nEventLoops, ExecutorFactory executorFactory) {
this(nEventLoops, executorFactory, SelectorProvider.provider());
public NioEventLoopGroup(int nEventLoops, ExecutorServiceFactory executorServiceFactory) {
this(nEventLoops, executorServiceFactory, SelectorProvider.provider());
}
/**
@ -106,12 +106,13 @@ public class NioEventLoopGroup extends MultithreadEventLoopGroup {
* requested from the default executor. It is generally advised for the number
* of {@link EventLoop}s and the number of {@link Thread}s used by the
* {@code executor} to lie very close together.
* @param executorFactory the {@link ExecutorFactory} to use, or {@code null} if the default should be used.
* @param executorServiceFactory the {@link ExecutorServiceFactory} to use, or {@code null} if the
* default should be used.
* @param selectorProvider the {@link SelectorProvider} to use. This value must not be {@code null}.
*/
public NioEventLoopGroup(
int nEventLoops, ExecutorFactory executorFactory, final SelectorProvider selectorProvider) {
super(nEventLoops, executorFactory, selectorProvider);
int nEventLoops, ExecutorServiceFactory executorServiceFactory, final SelectorProvider selectorProvider) {
super(nEventLoops, executorServiceFactory, selectorProvider);
}
/**

View File

@ -19,11 +19,10 @@ import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import io.netty.channel.local.LocalChannel;
import io.netty.util.concurrent.DefaultExecutorFactory;
import io.netty.util.concurrent.DefaultExecutorServiceFactory;
import io.netty.util.concurrent.EventExecutor;
import io.netty.util.concurrent.PausableEventExecutor;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@ -62,7 +61,7 @@ public class SingleThreadEventLoopTest {
@BeforeClass
public static void newExecutor() {
executor = new DefaultExecutorFactory("SingleThreadEventLoopTest").newExecutor(2);
executor = new DefaultExecutorServiceFactory("SingleThreadEventLoopTest").newExecutorService(2);
}
@Before

View File

@ -19,7 +19,7 @@ package io.netty.channel;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.DefaultExecutorFactory;
import io.netty.util.concurrent.DefaultExecutorServiceFactory;
import io.netty.util.concurrent.DefaultPromise;
import io.netty.util.concurrent.EventExecutor;
import io.netty.util.concurrent.GlobalEventExecutor;
@ -92,7 +92,7 @@ public class ThreadPerChannelEventLoopGroupTest {
private static final class TestEventExecutor extends SingleThreadEventExecutor {
TestEventExecutor() {
super(null, new DefaultExecutorFactory(TestEventExecutor.class).newExecutor(1), false);
super(null, new DefaultExecutorServiceFactory(TestEventExecutor.class).newExecutorService(1), false);
}
@Override

View File

@ -27,24 +27,16 @@ import io.netty.channel.DefaultEventLoopGroup;
import io.netty.channel.EventLoopGroup;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.concurrent.DefaultEventExecutorGroup;
import io.netty.util.concurrent.DefaultExecutorFactory;
import io.netty.util.concurrent.DefaultExecutorServiceFactory;
import io.netty.util.concurrent.EventExecutorGroup;
import io.netty.util.concurrent.ExecutorFactory;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
public class LocalTransportThreadModelTest {
@ -90,9 +82,9 @@ public class LocalTransportThreadModelTest {
@Test(timeout = 5000)
public void testStagedExecution() throws Throwable {
EventLoopGroup l = new DefaultEventLoopGroup(4, new DefaultExecutorFactory("l"));
EventExecutorGroup e1 = new DefaultEventExecutorGroup(4, new DefaultExecutorFactory("e1"));
EventExecutorGroup e2 = new DefaultEventExecutorGroup(4, new DefaultExecutorFactory("e2"));
EventLoopGroup l = new DefaultEventLoopGroup(4, new DefaultExecutorServiceFactory("l"));
EventExecutorGroup e1 = new DefaultEventExecutorGroup(4, new DefaultExecutorServiceFactory("e1"));
EventExecutorGroup e2 = new DefaultEventExecutorGroup(4, new DefaultExecutorServiceFactory("e2"));
ThreadNameAuditor h1 = new ThreadNameAuditor();
ThreadNameAuditor h2 = new ThreadNameAuditor();
ThreadNameAuditor h3 = new ThreadNameAuditor(true);
@ -214,12 +206,12 @@ public class LocalTransportThreadModelTest {
@Test(timeout = 30000)
@Ignore
public void testConcurrentMessageBufferAccess() throws Throwable {
EventLoopGroup l0 = new DefaultEventLoopGroup(4, new DefaultExecutorFactory("l0"));
EventExecutorGroup e1 = new DefaultEventExecutorGroup(4, new DefaultExecutorFactory("e1"));
EventExecutorGroup e2 = new DefaultEventExecutorGroup(4, new DefaultExecutorFactory("e2"));
EventExecutorGroup e3 = new DefaultEventExecutorGroup(4, new DefaultExecutorFactory("e3"));
EventExecutorGroup e4 = new DefaultEventExecutorGroup(4, new DefaultExecutorFactory("e4"));
EventExecutorGroup e5 = new DefaultEventExecutorGroup(4, new DefaultExecutorFactory("e5"));
EventLoopGroup l0 = new DefaultEventLoopGroup(4, new DefaultExecutorServiceFactory("l0"));
EventExecutorGroup e1 = new DefaultEventExecutorGroup(4, new DefaultExecutorServiceFactory("e1"));
EventExecutorGroup e2 = new DefaultEventExecutorGroup(4, new DefaultExecutorServiceFactory("e2"));
EventExecutorGroup e3 = new DefaultEventExecutorGroup(4, new DefaultExecutorServiceFactory("e3"));
EventExecutorGroup e4 = new DefaultEventExecutorGroup(4, new DefaultExecutorServiceFactory("e4"));
EventExecutorGroup e5 = new DefaultEventExecutorGroup(4, new DefaultExecutorServiceFactory("e5"));
try {
final MessageForwarder1 h1 = new MessageForwarder1();

View File

@ -26,7 +26,7 @@ import io.netty.channel.DefaultEventLoopGroup;
import io.netty.channel.EventLoopGroup;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.concurrent.DefaultEventExecutorGroup;
import io.netty.util.concurrent.DefaultExecutorFactory;
import io.netty.util.concurrent.DefaultExecutorServiceFactory;
import io.netty.util.concurrent.EventExecutorGroup;
import org.junit.AfterClass;
import org.junit.Assert;
@ -116,12 +116,12 @@ public class LocalTransportThreadModelTest3 {
}
private static void testConcurrentAddRemove(boolean inbound) throws Exception {
EventLoopGroup l = new DefaultEventLoopGroup(4, new DefaultExecutorFactory("l"));
EventExecutorGroup e1 = new DefaultEventExecutorGroup(4, new DefaultExecutorFactory("e1"));
EventExecutorGroup e2 = new DefaultEventExecutorGroup(4, new DefaultExecutorFactory("e2"));
EventExecutorGroup e3 = new DefaultEventExecutorGroup(4, new DefaultExecutorFactory("e3"));
EventExecutorGroup e4 = new DefaultEventExecutorGroup(4, new DefaultExecutorFactory("e4"));
EventExecutorGroup e5 = new DefaultEventExecutorGroup(4, new DefaultExecutorFactory("e5"));
EventLoopGroup l = new DefaultEventLoopGroup(4, new DefaultExecutorServiceFactory("l"));
EventExecutorGroup e1 = new DefaultEventExecutorGroup(4, new DefaultExecutorServiceFactory("e1"));
EventExecutorGroup e2 = new DefaultEventExecutorGroup(4, new DefaultExecutorServiceFactory("e2"));
EventExecutorGroup e3 = new DefaultEventExecutorGroup(4, new DefaultExecutorServiceFactory("e3"));
EventExecutorGroup e4 = new DefaultEventExecutorGroup(4, new DefaultExecutorServiceFactory("e4"));
EventExecutorGroup e5 = new DefaultEventExecutorGroup(4, new DefaultExecutorServiceFactory("e5"));
final EventExecutorGroup[] groups = { e1, e2, e3, e4, e5 };
try {