Add MultithreadEventLoopGroup.DEFAULT_EVENT_LOOP_THREADS / Add DefaultThreadFactory
- Allow overriding the default thread factory when a user specified no thread factory
This commit is contained in:
parent
312a35dfed
commit
117ad8acd7
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2013 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package io.netty.util.concurrent;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* A {@link ThreadFactory} implementation with a simple naming rule.
|
||||
*/
|
||||
public class DefaultThreadFactory implements ThreadFactory {
|
||||
|
||||
private static final AtomicInteger poolId = new AtomicInteger();
|
||||
|
||||
private final AtomicInteger nextId = new AtomicInteger();
|
||||
private final String prefix;
|
||||
private final boolean daemon;
|
||||
private final int priority;
|
||||
|
||||
public DefaultThreadFactory(Class<?> poolType) {
|
||||
this(poolType, false, Thread.NORM_PRIORITY);
|
||||
}
|
||||
|
||||
public DefaultThreadFactory(String poolName) {
|
||||
this(poolName, false, Thread.NORM_PRIORITY);
|
||||
}
|
||||
|
||||
public DefaultThreadFactory(Class<?> poolType, boolean daemon) {
|
||||
this(poolType, daemon, Thread.NORM_PRIORITY);
|
||||
}
|
||||
|
||||
public DefaultThreadFactory(String poolName, boolean daemon) {
|
||||
this(poolName, daemon, Thread.NORM_PRIORITY);
|
||||
}
|
||||
|
||||
public DefaultThreadFactory(Class<?> poolType, int priority) {
|
||||
this(poolType, false, priority);
|
||||
}
|
||||
|
||||
public DefaultThreadFactory(String poolName, int priority) {
|
||||
this(poolName, false, priority);
|
||||
}
|
||||
|
||||
public DefaultThreadFactory(Class<?> poolType, boolean daemon, int priority) {
|
||||
this(toPoolName(poolType), daemon, priority);
|
||||
}
|
||||
|
||||
private static String toPoolName(Class<?> poolType) {
|
||||
if (poolType == null) {
|
||||
throw new NullPointerException("poolType");
|
||||
}
|
||||
String poolName;
|
||||
Package pkg = poolType.getPackage();
|
||||
if (pkg != null) {
|
||||
poolName = poolType.getName().substring(pkg.getName().length() + 1);
|
||||
} else {
|
||||
poolName = poolType.getName();
|
||||
}
|
||||
|
||||
switch (poolName.length()) {
|
||||
case 0:
|
||||
return "unknown";
|
||||
case 1:
|
||||
return poolName.toLowerCase(Locale.US);
|
||||
default:
|
||||
if (Character.isUpperCase(poolName.charAt(0)) && Character.isLowerCase(poolName.charAt(1))) {
|
||||
return Character.toLowerCase(poolName.charAt(0)) + poolName.substring(1);
|
||||
} else {
|
||||
return poolName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public DefaultThreadFactory(String poolName, boolean daemon, int priority) {
|
||||
if (poolName == null) {
|
||||
throw new NullPointerException("poolName");
|
||||
}
|
||||
if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
|
||||
throw new IllegalArgumentException(
|
||||
"priority: " + priority + " (expected: Thread.MIN_PRIORITY <= priority <= Thread.MAX_PRIORITY)");
|
||||
}
|
||||
|
||||
prefix = poolName + '-' + poolId.incrementAndGet() + '-';
|
||||
this.daemon = daemon;
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread t = new Thread(r, prefix + nextId.incrementAndGet());
|
||||
try {
|
||||
if (t.isDaemon()) {
|
||||
if (!daemon) {
|
||||
t.setDaemon(false);
|
||||
}
|
||||
} else {
|
||||
if (daemon) {
|
||||
t.setDaemon(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (t.getPriority() != priority) {
|
||||
t.setPriority(priority);
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
// Doesn't matter even if failed to set.
|
||||
}
|
||||
return t;
|
||||
}
|
||||
}
|
@ -28,8 +28,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
*/
|
||||
public abstract class MultithreadEventExecutorGroup extends AbstractEventExecutorGroup {
|
||||
|
||||
private static final AtomicInteger poolId = new AtomicInteger();
|
||||
|
||||
private final EventExecutor[] children;
|
||||
private final AtomicInteger childIndex = new AtomicInteger();
|
||||
|
||||
@ -46,7 +44,7 @@ public abstract class MultithreadEventExecutorGroup extends AbstractEventExecuto
|
||||
}
|
||||
|
||||
if (threadFactory == null) {
|
||||
threadFactory = new DefaultThreadFactory();
|
||||
threadFactory = newDefaultThreadFactory();
|
||||
}
|
||||
|
||||
children = new SingleThreadEventExecutor[nThreads];
|
||||
@ -68,6 +66,10 @@ public abstract class MultithreadEventExecutorGroup extends AbstractEventExecuto
|
||||
}
|
||||
}
|
||||
|
||||
protected ThreadFactory newDefaultThreadFactory() {
|
||||
return new DefaultThreadFactory(getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventExecutor next() {
|
||||
return children[Math.abs(childIndex.getAndIncrement() % children.length)];
|
||||
@ -138,31 +140,4 @@ public abstract class MultithreadEventExecutorGroup extends AbstractEventExecuto
|
||||
}
|
||||
return isTerminated();
|
||||
}
|
||||
|
||||
private final class DefaultThreadFactory implements ThreadFactory {
|
||||
private final AtomicInteger nextId = new AtomicInteger();
|
||||
private final String prefix;
|
||||
|
||||
DefaultThreadFactory() {
|
||||
String typeName = MultithreadEventExecutorGroup.this.getClass().getSimpleName();
|
||||
typeName = Character.toLowerCase(typeName.charAt(0)) + typeName.substring(1);
|
||||
prefix = typeName + '-' + poolId.incrementAndGet() + '-';
|
||||
}
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread t = new Thread(r, prefix + nextId.incrementAndGet());
|
||||
try {
|
||||
if (t.isDaemon()) {
|
||||
t.setDaemon(false);
|
||||
}
|
||||
if (t.getPriority() != Thread.MAX_PRIORITY) {
|
||||
t.setPriority(Thread.MAX_PRIORITY);
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
// Doesn't matter even if failed to set.
|
||||
}
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,11 @@
|
||||
*/
|
||||
package io.netty.channel;
|
||||
|
||||
import io.netty.util.concurrent.DefaultThreadFactory;
|
||||
import io.netty.util.concurrent.MultithreadEventExecutorGroup;
|
||||
import io.netty.util.internal.SystemPropertyUtil;
|
||||
import io.netty.util.internal.logging.InternalLogger;
|
||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
@ -25,13 +29,28 @@ import java.util.concurrent.ThreadFactory;
|
||||
*/
|
||||
public abstract class MultithreadEventLoopGroup extends MultithreadEventExecutorGroup implements EventLoopGroup {
|
||||
|
||||
/**
|
||||
* @see {@link MultithreadEventExecutorGroup##MultithreadEventLoopGroup(int,ThreadFactory, Object...)}
|
||||
*/
|
||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(MultithreadEventLoopGroup.class);
|
||||
|
||||
public static final int DEFAULT_EVENT_LOOP_THREADS;
|
||||
|
||||
static {
|
||||
DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
|
||||
"io.netty.eventLoopThreads", Runtime.getRuntime().availableProcessors() * 2));
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("io.netty.eventLoopThreads: {}", DEFAULT_EVENT_LOOP_THREADS);
|
||||
}
|
||||
}
|
||||
|
||||
protected MultithreadEventLoopGroup(int nThreads, ThreadFactory threadFactory, Object... args) {
|
||||
super(nThreads, threadFactory, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ThreadFactory newDefaultThreadFactory() {
|
||||
return new DefaultThreadFactory(getClass(), Thread.MAX_PRIORITY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventLoop next() {
|
||||
return (EventLoop) super.next();
|
||||
|
@ -42,17 +42,16 @@ public class AioEventLoopGroup extends MultithreadEventLoopGroup {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance which use the default number of threads of {@link #DEFAULT_POOL_SIZE}.
|
||||
* Create a new instance which use the default number of threads of {@link #DEFAULT_EVENT_LOOP_THREADS}.
|
||||
*/
|
||||
public AioEventLoopGroup() {
|
||||
this(0);
|
||||
this(DEFAULT_EVENT_LOOP_THREADS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance
|
||||
*
|
||||
* @param nThreads the number of threads that will be used by this instance. Use 0 for the default number
|
||||
* of {@link #DEFAULT_POOL_SIZE}
|
||||
* @param nThreads the number of threads that will be used by this instance
|
||||
*/
|
||||
public AioEventLoopGroup(int nThreads) {
|
||||
this(nThreads, null);
|
||||
@ -61,8 +60,7 @@ public class AioEventLoopGroup extends MultithreadEventLoopGroup {
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param nThreads the number of threads that will be used by this instance. Use 0 for the default number
|
||||
* of {@link #DEFAULT_POOL_SIZE}
|
||||
* @param nThreads the number of threads that will be used by this instance
|
||||
* @param threadFactory the ThreadFactory to use, or {@code null} if the default should be used.
|
||||
*/
|
||||
public AioEventLoopGroup(int nThreads, ThreadFactory threadFactory) {
|
||||
|
@ -26,16 +26,16 @@ import java.util.concurrent.ThreadFactory;
|
||||
public class LocalEventLoopGroup extends MultithreadEventLoopGroup {
|
||||
|
||||
/**
|
||||
* Create a new instance which used {@link #DEFAULT_POOL_SIZE} number of Threads
|
||||
* Create a new instance which used {@link #DEFAULT_EVENT_LOOP_THREADS} number of Threads
|
||||
*/
|
||||
public LocalEventLoopGroup() {
|
||||
this(0);
|
||||
this(DEFAULT_EVENT_LOOP_THREADS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance
|
||||
*
|
||||
* @param nThreads the number of Threads to use or {@code 0} for the default of {@link #DEFAULT_POOL_SIZE}
|
||||
* @param nThreads the number of threads to use
|
||||
*/
|
||||
public LocalEventLoopGroup(int nThreads) {
|
||||
this(nThreads, null);
|
||||
@ -44,7 +44,7 @@ public class LocalEventLoopGroup extends MultithreadEventLoopGroup {
|
||||
/**
|
||||
* Create a new instance
|
||||
*
|
||||
* @param nThreads the number of Threads to use or {@code 0} for the default of {@link #DEFAULT_POOL_SIZE}
|
||||
* @param nThreads the number of threads to use
|
||||
* @param threadFactory the {@link ThreadFactory} or {@code null} to use the default
|
||||
*/
|
||||
public LocalEventLoopGroup(int nThreads, ThreadFactory threadFactory) {
|
||||
|
@ -29,11 +29,11 @@ import java.util.concurrent.ThreadFactory;
|
||||
public class NioEventLoopGroup extends MultithreadEventLoopGroup {
|
||||
|
||||
/**
|
||||
* Create a new instance using {@link #DEFAULT_POOL_SIZE} number of threads, the default {@link ThreadFactory} and
|
||||
* the {@link SelectorProvider} which is returned by {@link SelectorProvider#provider()}.
|
||||
* Create a new instance using {@link #DEFAULT_EVENT_LOOP_THREADS} number of threads, the default
|
||||
* {@link ThreadFactory} and the {@link SelectorProvider} which is returned by {@link SelectorProvider#provider()}.
|
||||
*/
|
||||
public NioEventLoopGroup() {
|
||||
this(0);
|
||||
this(DEFAULT_EVENT_LOOP_THREADS);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user