189 lines
6.8 KiB
Java
189 lines
6.8 KiB
Java
![]() |
/*
|
||
|
* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
|
||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||
|
*
|
||
|
* This code is free software; you can redistribute it and/or modify it
|
||
|
* under the terms of the GNU General Public License version 2 only, as
|
||
|
* published by the Free Software Foundation. Oracle designates this
|
||
|
* particular file as subject to the "Classpath" exception as provided
|
||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||
|
*
|
||
|
* This code 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 General Public License
|
||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||
|
* accompanied this code).
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License version
|
||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||
|
*
|
||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||
|
* or visit www.oracle.com if you need additional information or have any
|
||
|
* questions.
|
||
|
*/
|
||
|
|
||
|
package sun.nio.ch;
|
||
|
|
||
|
import java.util.concurrent.*;
|
||
|
import java.security.AccessController;
|
||
|
import java.security.PrivilegedAction;
|
||
|
import sun.security.action.GetPropertyAction;
|
||
|
|
||
|
/**
|
||
|
* Encapsulates a thread pool associated with a channel group.
|
||
|
*/
|
||
|
|
||
|
public class ThreadPool {
|
||
|
private static final String DEFAULT_THREAD_POOL_THREAD_FACTORY =
|
||
|
"java.nio.channels.DefaultThreadPool.threadFactory";
|
||
|
private static final String DEFAULT_THREAD_POOL_INITIAL_SIZE =
|
||
|
"java.nio.channels.DefaultThreadPool.initialSize";
|
||
|
|
||
|
private final ExecutorService executor;
|
||
|
|
||
|
// indicates if thread pool is fixed size
|
||
|
private final boolean isFixed;
|
||
|
|
||
|
// indicates the pool size (for a fixed thread pool configuratin this is
|
||
|
// the maximum pool size; for other thread pools it is the initial size)
|
||
|
private final int poolSize;
|
||
|
|
||
|
private ThreadPool(ExecutorService executor,
|
||
|
boolean isFixed,
|
||
|
int poolSize)
|
||
|
{
|
||
|
this.executor = executor;
|
||
|
this.isFixed = isFixed;
|
||
|
this.poolSize = poolSize;
|
||
|
}
|
||
|
|
||
|
ExecutorService executor() {
|
||
|
return executor;
|
||
|
}
|
||
|
|
||
|
boolean isFixedThreadPool() {
|
||
|
return isFixed;
|
||
|
}
|
||
|
|
||
|
int poolSize() {
|
||
|
return poolSize;
|
||
|
}
|
||
|
|
||
|
static ThreadFactory defaultThreadFactory() {
|
||
|
// BEGIN Android-changed: System.getSecurityManager always returns null.
|
||
|
/*
|
||
|
if (System.getSecurityManager() == null) {
|
||
|
return (Runnable r) -> {
|
||
|
Thread t = new Thread(r);
|
||
|
t.setDaemon(true);
|
||
|
return t;
|
||
|
};
|
||
|
} else {
|
||
|
return (Runnable r) -> {
|
||
|
PrivilegedAction<Thread> action = () -> {
|
||
|
Thread t = new sun.misc.InnocuousThread(r);
|
||
|
t.setDaemon(true);
|
||
|
return t;
|
||
|
};
|
||
|
return AccessController.doPrivileged(action);
|
||
|
};
|
||
|
}
|
||
|
*/
|
||
|
return (Runnable r) -> {
|
||
|
Thread t = new Thread(r);
|
||
|
t.setDaemon(true);
|
||
|
return t;
|
||
|
};
|
||
|
// END Android-changed: System.getSecurityManager always returns null.
|
||
|
}
|
||
|
|
||
|
private static class DefaultThreadPoolHolder {
|
||
|
final static ThreadPool defaultThreadPool = createDefault();
|
||
|
}
|
||
|
|
||
|
// return the default (system-wide) thread pool
|
||
|
static ThreadPool getDefault() {
|
||
|
return DefaultThreadPoolHolder.defaultThreadPool;
|
||
|
}
|
||
|
|
||
|
// create thread using default settings (configured by system properties)
|
||
|
static ThreadPool createDefault() {
|
||
|
// default the number of fixed threads to the hardware core count
|
||
|
int initialSize = getDefaultThreadPoolInitialSize();
|
||
|
if (initialSize < 0)
|
||
|
initialSize = Runtime.getRuntime().availableProcessors();
|
||
|
// default to thread factory that creates daemon threads
|
||
|
ThreadFactory threadFactory = getDefaultThreadPoolThreadFactory();
|
||
|
if (threadFactory == null)
|
||
|
threadFactory = defaultThreadFactory();
|
||
|
// create thread pool
|
||
|
ExecutorService executor = Executors.newCachedThreadPool(threadFactory);
|
||
|
return new ThreadPool(executor, false, initialSize);
|
||
|
}
|
||
|
|
||
|
// create using given parameters
|
||
|
static ThreadPool create(int nThreads, ThreadFactory factory) {
|
||
|
if (nThreads <= 0)
|
||
|
throw new IllegalArgumentException("'nThreads' must be > 0");
|
||
|
ExecutorService executor = Executors.newFixedThreadPool(nThreads, factory);
|
||
|
return new ThreadPool(executor, true, nThreads);
|
||
|
}
|
||
|
|
||
|
// wrap a user-supplied executor
|
||
|
public static ThreadPool wrap(ExecutorService executor, int initialSize) {
|
||
|
if (executor == null)
|
||
|
throw new NullPointerException("'executor' is null");
|
||
|
// attempt to check if cached thread pool
|
||
|
if (executor instanceof ThreadPoolExecutor) {
|
||
|
int max = ((ThreadPoolExecutor)executor).getMaximumPoolSize();
|
||
|
if (max == Integer.MAX_VALUE) {
|
||
|
if (initialSize < 0) {
|
||
|
initialSize = Runtime.getRuntime().availableProcessors();
|
||
|
} else {
|
||
|
// not a cached thread pool so ignore initial size
|
||
|
initialSize = 0;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
// some other type of thread pool
|
||
|
if (initialSize < 0)
|
||
|
initialSize = 0;
|
||
|
}
|
||
|
return new ThreadPool(executor, false, initialSize);
|
||
|
}
|
||
|
|
||
|
private static int getDefaultThreadPoolInitialSize() {
|
||
|
String propValue = AccessController.doPrivileged(new
|
||
|
GetPropertyAction(DEFAULT_THREAD_POOL_INITIAL_SIZE));
|
||
|
if (propValue != null) {
|
||
|
try {
|
||
|
return Integer.parseInt(propValue);
|
||
|
} catch (NumberFormatException x) {
|
||
|
throw new Error("Value of property '" + DEFAULT_THREAD_POOL_INITIAL_SIZE +
|
||
|
"' is invalid: " + x);
|
||
|
}
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
private static ThreadFactory getDefaultThreadPoolThreadFactory() {
|
||
|
String propValue = AccessController.doPrivileged(new
|
||
|
GetPropertyAction(DEFAULT_THREAD_POOL_THREAD_FACTORY));
|
||
|
if (propValue != null) {
|
||
|
try {
|
||
|
Class<?> c = Class
|
||
|
.forName(propValue, true, ClassLoader.getSystemClassLoader());
|
||
|
return ((ThreadFactory)c.newInstance());
|
||
|
} catch (ClassNotFoundException x) {
|
||
|
throw new Error(x);
|
||
|
} catch (InstantiationException x) {
|
||
|
throw new Error(x);
|
||
|
} catch (IllegalAccessException x) {
|
||
|
throw new Error(x);
|
||
|
}
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
}
|