An IoProcessor pool that distributes IoSessions into one or more IoProcessors.
Most current transport implementations use this pool internally to perform better in a multi-core environment.
and therefore, you won't need to use this pool directly unless you are running multiple IoServices in the same JVM.
SimpleIoProcessorPool 主要处理IO输入输出线程池的管理。主要功能为创建线程池,把IoSession与IoProcessor线程相关联,管理IoProcessor线程。
其中,IoProcessor线程与IoSession相关联的代码如下,这就意味着一个线程同时处理多个IoSession的输入输出操作。
/**
* 根据IoSession ID和线程池的顺序把线程和IoSession相关联在一起
* Find the processor associated to a session. If it hasen't be stored into
* the session's attributes, pick a new processor and stores it.
*/
@SuppressWarnings("unchecked")
private IoProcessor<S> getProcessor(S session) {
IoProcessor<S> processor = (IoProcessor<S>) session.getAttribute(PROCESSOR);
if (processor == null) {
if (disposed || disposing) {
throw new IllegalStateException("A disposed processor cannot be accessed.");
}
processor = pool[Math.abs((int) session.getId()) % pool.length];
if (processor == null) {
throw new IllegalStateException("A disposed processor cannot be accessed.");
}
session.setAttributeIfAbsent(PROCESSOR, processor);
}
return processor;
}
当IoSession和IoProcessor相关联后,IoProcessor的生命周期交由Executor来管理。
/**
* 在把IoSession和IoProcessor相关联后,调用startupProcessor()方法,把IoProcessor交由Executor关联
*/
public final void add(S session) {
getProcessor(session).add(session);
}
public final void add(S session) {
if (disposed || disposing) {
throw new IllegalStateException("Already disposed.");
}
// Adds the session to the newSession queue and starts the worker
newSessions.add(session);
startupProcessor();
}
/**
* Starts the inner Processor, asking the executor to pick a thread in its
* pool. The Runnable will be renamed
*/
private void startupProcessor() {
Processor processor = processorRef.get();
if (processor == null) {
processor = new Processor();
if (processorRef.compareAndSet(null, processor)) {
executor.execute(new NamePreservingRunnable(processor, threadName));
}
}
// Just stop the select() and start it again, so that the processor
// can be activated immediately.
wakeup();
}
SimpleIoProcessorPool的成员字段如下:
public class SimpleIoProcessorPool<S extends AbstractIoSession> implements IoProcessor<S> {
/** A logger for this class */
private final static Logger LOGGER = LoggerFactory.getLogger(SimpleIoProcessorPool.class);
/** The default pool size, when no size is provided. */
//创建默认线程的数量
private static final int DEFAULT_SIZE = Runtime.getRuntime().availableProcessors() + 1;
/** A key used to store the processor pool in the session's Attributes */
//在IoSession持有IoProcessor的标记
private static final AttributeKey PROCESSOR = new AttributeKey(SimpleIoProcessorPool.class, "processor");
/** The pool table */
//线程池
private final IoProcessor<S>[] pool;
/** The contained which is passed to the IoProcessor when they are created */
private final Executor executor;
/** A flag set to true if we had to create an executor */
private final boolean createdExecutor;
/** A lock to protect the disposal against concurrent calls */
private final Object disposalLock = new Object();
/** A flg set to true if the IoProcessor in the pool are being disposed */
private volatile boolean disposing;
/** A flag set to true if all the IoProcessor contained in the pool have been disposed */
private volatile boolean disposed;
}
private static final int DEFAULT_SIZE = Runtime.getRuntime().availableProcessors() + 1;
线程也都是预先创建好,等待IO操作产生时,减少线程创建的时间。
/**
* Creates a new instance of SimpleIoProcessorPool with an executor
*
* @param processorType The type of IoProcessor to use
* @param executor The {@link Executor}
* @param size The number of IoProcessor in the pool
*/
@SuppressWarnings("unchecked")
public SimpleIoProcessorPool(Class<? extends IoProcessor<S>> processorType, Executor executor, int size, SelectorProvider selectorProvider) {
if (processorType == null) {
throw new IllegalArgumentException("processorType");
}
if (size <= 0) {
throw new IllegalArgumentException("size: " + size + " (expected: positive integer)");
}
// Create the executor if none is provided
createdExecutor = (executor == null);
if (createdExecutor) {
this.executor = Executors.newCachedThreadPool();
// Set a default reject handler
((ThreadPoolExecutor) this.executor).setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
} else {
this.executor = executor;
}
pool = new IoProcessor[size];
boolean success = false;
Constructor<? extends IoProcessor<S>> processorConstructor = null;
boolean usesExecutorArg = true;
try {
// We create at least one processor
try {
try {
processorConstructor = processorType.getConstructor(ExecutorService.class);
pool[0] = processorConstructor.newInstance(this.executor);
} catch (NoSuchMethodException e1) {
// To the next step...
try {
if(selectorProvider==null) {
processorConstructor = processorType.getConstructor(Executor.class);
pool[0] = processorConstructor.newInstance(this.executor);
} else {
processorConstructor = processorType.getConstructor(Executor.class, SelectorProvider.class);
pool[0] = processorConstructor.newInstance(this.executor,selectorProvider);
}
} catch (NoSuchMethodException e2) {
// To the next step...
try {
processorConstructor = processorType.getConstructor();
usesExecutorArg = false;
pool[0] = processorConstructor.newInstance();
} catch (NoSuchMethodException e3) {
// To the next step...
}
}
}
} catch (RuntimeException re) {
LOGGER.error("Cannot create an IoProcessor :{}", re.getMessage());
throw re;
} catch (Exception e) {
String msg = "Failed to create a new instance of " + processorType.getName() + ":" + e.getMessage();
LOGGER.error(msg, e);
throw new RuntimeIoException(msg, e);
}
if (processorConstructor == null) {
// Raise an exception if no proper constructor is found.
String msg = String.valueOf(processorType) + " must have a public constructor with one "
+ ExecutorService.class.getSimpleName() + " parameter, a public constructor with one "
+ Executor.class.getSimpleName() + " parameter or a public default constructor.";
LOGGER.error(msg);
throw new IllegalArgumentException(msg);
}
// Constructor found now use it for all subsequent instantiations
for (int i = 1; i < pool.length; i++) {
try {
if (usesExecutorArg) {
if(selectorProvider==null) {
pool[i] = processorConstructor.newInstance(this.executor);
} else {
pool[i] = processorConstructor.newInstance(this.executor, selectorProvider);
}
} else {
pool[i] = processorConstructor.newInstance();
}
} catch (Exception e) {
// Won't happen because it has been done previously
}
}
success = true;
} finally {
if (!success) {
dispose();
}
}
}