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 // Android-changed: System.getSecurityManager always returns null. 75 // if (System.getSecurityManager() == null) { 76 return (Runnable r) -> { 77 Thread t = new Thread(r); 78 t.setDaemon(true); 79 return t; 80 }; 81 // } else { 82 // return (Runnable r) -> { 83 // PrivilegedAction<Thread> action = () -> { 84 // Thread t = new sun.misc.InnocuousThread(r); 85 // t.setDaemon(true); 86 // return t; 87 // }; 88 // return AccessController.doPrivileged(action); 89 // }; 90 // } 91 } 92 93 private static class DefaultThreadPoolHolder { 94 final static ThreadPool defaultThreadPool = createDefault(); 95 } 96 97 // return the default (system-wide) thread pool getDefault()98 static ThreadPool getDefault() { 99 return DefaultThreadPoolHolder.defaultThreadPool; 100 } 101 102 // create thread using default settings (configured by system properties) createDefault()103 static ThreadPool createDefault() { 104 // default the number of fixed threads to the hardware core count 105 int initialSize = getDefaultThreadPoolInitialSize(); 106 if (initialSize < 0) 107 initialSize = Runtime.getRuntime().availableProcessors(); 108 // default to thread factory that creates daemon threads 109 ThreadFactory threadFactory = getDefaultThreadPoolThreadFactory(); 110 if (threadFactory == null) 111 threadFactory = defaultThreadFactory(); 112 // create thread pool 113 ExecutorService executor = Executors.newCachedThreadPool(threadFactory); 114 return new ThreadPool(executor, false, initialSize); 115 } 116 117 // create using given parameters create(int nThreads, ThreadFactory factory)118 static ThreadPool create(int nThreads, ThreadFactory factory) { 119 if (nThreads <= 0) 120 throw new IllegalArgumentException("'nThreads' must be > 0"); 121 ExecutorService executor = Executors.newFixedThreadPool(nThreads, factory); 122 return new ThreadPool(executor, true, nThreads); 123 } 124 125 // wrap a user-supplied executor wrap(ExecutorService executor, int initialSize)126 public static ThreadPool wrap(ExecutorService executor, int initialSize) { 127 if (executor == null) 128 throw new NullPointerException("'executor' is null"); 129 // attempt to check if cached thread pool 130 if (executor instanceof ThreadPoolExecutor) { 131 int max = ((ThreadPoolExecutor)executor).getMaximumPoolSize(); 132 if (max == Integer.MAX_VALUE) { 133 if (initialSize < 0) { 134 initialSize = Runtime.getRuntime().availableProcessors(); 135 } else { 136 // not a cached thread pool so ignore initial size 137 initialSize = 0; 138 } 139 } 140 } else { 141 // some other type of thread pool 142 if (initialSize < 0) 143 initialSize = 0; 144 } 145 return new ThreadPool(executor, false, initialSize); 146 } 147 getDefaultThreadPoolInitialSize()148 private static int getDefaultThreadPoolInitialSize() { 149 String propValue = AccessController.doPrivileged(new 150 GetPropertyAction(DEFAULT_THREAD_POOL_INITIAL_SIZE)); 151 if (propValue != null) { 152 try { 153 return Integer.parseInt(propValue); 154 } catch (NumberFormatException x) { 155 throw new Error("Value of property '" + DEFAULT_THREAD_POOL_INITIAL_SIZE + 156 "' is invalid: " + x); 157 } 158 } 159 return -1; 160 } 161 getDefaultThreadPoolThreadFactory()162 private static ThreadFactory getDefaultThreadPoolThreadFactory() { 163 String propValue = AccessController.doPrivileged(new 164 GetPropertyAction(DEFAULT_THREAD_POOL_THREAD_FACTORY)); 165 if (propValue != null) { 166 try { 167 Class<?> c = Class 168 .forName(propValue, true, ClassLoader.getSystemClassLoader()); 169 return ((ThreadFactory)c.newInstance()); 170 } catch (ClassNotFoundException x) { 171 throw new Error(x); 172 } catch (InstantiationException x) { 173 throw new Error(x); 174 } catch (IllegalAccessException x) { 175 throw new Error(x); 176 } 177 } 178 return null; 179 } 180 } 181