1 /* 2 * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.nio.ch; 27 28 import java.util.concurrent.*; 29 import java.security.AccessController; 30 import java.security.PrivilegedAction; 31 import sun.security.action.GetPropertyAction; 32 33 /** 34 * Encapsulates a thread pool associated with a channel group. 35 */ 36 37 public class ThreadPool { 38 private static final String DEFAULT_THREAD_POOL_THREAD_FACTORY = 39 "java.nio.channels.DefaultThreadPool.threadFactory"; 40 private static final String DEFAULT_THREAD_POOL_INITIAL_SIZE = 41 "java.nio.channels.DefaultThreadPool.initialSize"; 42 43 private final ExecutorService executor; 44 45 // indicates if thread pool is fixed size 46 private final boolean isFixed; 47 48 // indicates the pool size (for a fixed thread pool configuratin this is 49 // the maximum pool size; for other thread pools it is the initial size) 50 private final int poolSize; 51 ThreadPool(ExecutorService executor, boolean isFixed, int poolSize)52 private ThreadPool(ExecutorService executor, 53 boolean isFixed, 54 int poolSize) 55 { 56 this.executor = executor; 57 this.isFixed = isFixed; 58 this.poolSize = poolSize; 59 } 60 executor()61 ExecutorService executor() { 62 return executor; 63 } 64 isFixedThreadPool()65 boolean isFixedThreadPool() { 66 return isFixed; 67 } 68 poolSize()69 int poolSize() { 70 return poolSize; 71 } 72 defaultThreadFactory()73 static ThreadFactory defaultThreadFactory() { 74 // BEGIN Android-changed: System.getSecurityManager always returns null. 75 /* 76 if (System.getSecurityManager() == null) { 77 return (Runnable r) -> { 78 Thread t = new Thread(r); 79 t.setDaemon(true); 80 return t; 81 }; 82 } else { 83 return (Runnable r) -> { 84 PrivilegedAction<Thread> action = () -> { 85 Thread t = new sun.misc.InnocuousThread(r); 86 t.setDaemon(true); 87 return t; 88 }; 89 return AccessController.doPrivileged(action); 90 }; 91 } 92 */ 93 return (Runnable r) -> { 94 Thread t = new Thread(r); 95 t.setDaemon(true); 96 return t; 97 }; 98 // END Android-changed: System.getSecurityManager always returns null. 99 } 100 101 private static class DefaultThreadPoolHolder { 102 final static ThreadPool defaultThreadPool = createDefault(); 103 } 104 105 // return the default (system-wide) thread pool getDefault()106 static ThreadPool getDefault() { 107 return DefaultThreadPoolHolder.defaultThreadPool; 108 } 109 110 // create thread using default settings (configured by system properties) createDefault()111 static ThreadPool createDefault() { 112 // default the number of fixed threads to the hardware core count 113 int initialSize = getDefaultThreadPoolInitialSize(); 114 if (initialSize < 0) 115 initialSize = Runtime.getRuntime().availableProcessors(); 116 // default to thread factory that creates daemon threads 117 ThreadFactory threadFactory = getDefaultThreadPoolThreadFactory(); 118 if (threadFactory == null) 119 threadFactory = defaultThreadFactory(); 120 // create thread pool 121 ExecutorService executor = Executors.newCachedThreadPool(threadFactory); 122 return new ThreadPool(executor, false, initialSize); 123 } 124 125 // create using given parameters create(int nThreads, ThreadFactory factory)126 static ThreadPool create(int nThreads, ThreadFactory factory) { 127 if (nThreads <= 0) 128 throw new IllegalArgumentException("'nThreads' must be > 0"); 129 ExecutorService executor = Executors.newFixedThreadPool(nThreads, factory); 130 return new ThreadPool(executor, true, nThreads); 131 } 132 133 // wrap a user-supplied executor wrap(ExecutorService executor, int initialSize)134 public static ThreadPool wrap(ExecutorService executor, int initialSize) { 135 if (executor == null) 136 throw new NullPointerException("'executor' is null"); 137 // attempt to check if cached thread pool 138 if (executor instanceof ThreadPoolExecutor) { 139 int max = ((ThreadPoolExecutor)executor).getMaximumPoolSize(); 140 if (max == Integer.MAX_VALUE) { 141 if (initialSize < 0) { 142 initialSize = Runtime.getRuntime().availableProcessors(); 143 } else { 144 // not a cached thread pool so ignore initial size 145 initialSize = 0; 146 } 147 } 148 } else { 149 // some other type of thread pool 150 if (initialSize < 0) 151 initialSize = 0; 152 } 153 return new ThreadPool(executor, false, initialSize); 154 } 155 getDefaultThreadPoolInitialSize()156 private static int getDefaultThreadPoolInitialSize() { 157 String propValue = AccessController.doPrivileged(new 158 GetPropertyAction(DEFAULT_THREAD_POOL_INITIAL_SIZE)); 159 if (propValue != null) { 160 try { 161 return Integer.parseInt(propValue); 162 } catch (NumberFormatException x) { 163 throw new Error("Value of property '" + DEFAULT_THREAD_POOL_INITIAL_SIZE + 164 "' is invalid: " + x); 165 } 166 } 167 return -1; 168 } 169 getDefaultThreadPoolThreadFactory()170 private static ThreadFactory getDefaultThreadPoolThreadFactory() { 171 String propValue = AccessController.doPrivileged(new 172 GetPropertyAction(DEFAULT_THREAD_POOL_THREAD_FACTORY)); 173 if (propValue != null) { 174 try { 175 Class<?> c = Class 176 .forName(propValue, true, ClassLoader.getSystemClassLoader()); 177 return ((ThreadFactory)c.newInstance()); 178 } catch (ClassNotFoundException x) { 179 throw new Error(x); 180 } catch (InstantiationException x) { 181 throw new Error(x); 182 } catch (IllegalAccessException x) { 183 throw new Error(x); 184 } 185 } 186 return null; 187 } 188 } 189