1 /* 2 * Copyright (c) 2008, 2009, 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 sun.security.action.GetPropertyAction; 31 import sun.security.action.GetIntegerAction; 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 private static final ThreadFactory defaultThreadFactory = new ThreadFactory() { 43 @Override 44 public Thread newThread(Runnable r) { 45 Thread t = new Thread(r); 46 t.setDaemon(true); 47 return t; 48 } 49 }; 50 51 private final ExecutorService executor; 52 53 // indicates if thread pool is fixed size 54 private final boolean isFixed; 55 56 // indicates the pool size (for a fixed thread pool configuratin this is 57 // the maximum pool size; for other thread pools it is the initial size) 58 private final int poolSize; 59 ThreadPool(ExecutorService executor, boolean isFixed, int poolSize)60 private ThreadPool(ExecutorService executor, 61 boolean isFixed, 62 int poolSize) 63 { 64 this.executor = executor; 65 this.isFixed = isFixed; 66 this.poolSize = poolSize; 67 } 68 executor()69 ExecutorService executor() { 70 return executor; 71 } 72 isFixedThreadPool()73 boolean isFixedThreadPool() { 74 return isFixed; 75 } 76 poolSize()77 int poolSize() { 78 return poolSize; 79 } 80 defaultThreadFactory()81 static ThreadFactory defaultThreadFactory() { 82 return defaultThreadFactory; 83 } 84 85 private static class DefaultThreadPoolHolder { 86 final static ThreadPool defaultThreadPool = createDefault(); 87 } 88 89 // return the default (system-wide) thread pool getDefault()90 static ThreadPool getDefault() { 91 return DefaultThreadPoolHolder.defaultThreadPool; 92 } 93 94 // create thread using default settings (configured by system properties) createDefault()95 static ThreadPool createDefault() { 96 // default the number of fixed threads to the hardware core count 97 int initialSize = getDefaultThreadPoolInitialSize(); 98 if (initialSize < 0) 99 initialSize = Runtime.getRuntime().availableProcessors(); 100 // default to thread factory that creates daemon threads 101 ThreadFactory threadFactory = getDefaultThreadPoolThreadFactory(); 102 if (threadFactory == null) 103 threadFactory = defaultThreadFactory; 104 // create thread pool 105 ExecutorService executor = 106 new ThreadPoolExecutor(0, Integer.MAX_VALUE, 107 Long.MAX_VALUE, TimeUnit.MILLISECONDS, 108 new SynchronousQueue<Runnable>(), 109 threadFactory); 110 return new ThreadPool(executor, false, initialSize); 111 } 112 113 // create using given parameters create(int nThreads, ThreadFactory factory)114 static ThreadPool create(int nThreads, ThreadFactory factory) { 115 if (nThreads <= 0) 116 throw new IllegalArgumentException("'nThreads' must be > 0"); 117 ExecutorService executor = Executors.newFixedThreadPool(nThreads, factory); 118 return new ThreadPool(executor, true, nThreads); 119 } 120 121 // wrap a user-supplied executor wrap(ExecutorService executor, int initialSize)122 public static ThreadPool wrap(ExecutorService executor, int initialSize) { 123 if (executor == null) 124 throw new NullPointerException("'executor' is null"); 125 // attempt to check if cached thread pool 126 if (executor instanceof ThreadPoolExecutor) { 127 int max = ((ThreadPoolExecutor)executor).getMaximumPoolSize(); 128 if (max == Integer.MAX_VALUE) { 129 if (initialSize < 0) { 130 initialSize = Runtime.getRuntime().availableProcessors(); 131 } else { 132 // not a cached thread pool so ignore initial size 133 initialSize = 0; 134 } 135 } 136 } else { 137 // some other type of thread pool 138 if (initialSize < 0) 139 initialSize = 0; 140 } 141 return new ThreadPool(executor, false, initialSize); 142 } 143 getDefaultThreadPoolInitialSize()144 private static int getDefaultThreadPoolInitialSize() { 145 String propValue = AccessController.doPrivileged(new 146 GetPropertyAction(DEFAULT_THREAD_POOL_INITIAL_SIZE)); 147 if (propValue != null) { 148 try { 149 return Integer.parseInt(propValue); 150 } catch (NumberFormatException x) { 151 throw new Error("Value of property '" + DEFAULT_THREAD_POOL_INITIAL_SIZE + 152 "' is invalid: " + x); 153 } 154 } 155 return -1; 156 } 157 getDefaultThreadPoolThreadFactory()158 private static ThreadFactory getDefaultThreadPoolThreadFactory() { 159 String propValue = AccessController.doPrivileged(new 160 GetPropertyAction(DEFAULT_THREAD_POOL_THREAD_FACTORY)); 161 if (propValue != null) { 162 try { 163 Class<?> c = Class 164 .forName(propValue, true, ClassLoader.getSystemClassLoader()); 165 return ((ThreadFactory)c.newInstance()); 166 } catch (ClassNotFoundException x) { 167 throw new Error(x); 168 } catch (InstantiationException x) { 169 throw new Error(x); 170 } catch (IllegalAccessException x) { 171 throw new Error(x); 172 } 173 } 174 return null; 175 } 176 } 177