/* * @(#)ThreadPoolExecutor.java */ package java.util.concurrent; import java.util.List; /** * A {@link ThreadedExecutor} that executes each submitted task on one * of several pooled threads. * *

Thread pools address two different problems at the same time: * they usually provide improved performance when executing large * numbers of asynchronous tasks, due to reduced per-task invocation * overhead, and they provide a means of bounding and managing the * resources, including threads, consumed in executing a collection of * tasks. * *

This class is very configurable and can be configured to create * a new thread for each task, or even to execute tasks sequentially * in a single thread, in addition to its most common configuration, * which reuses a pool of threads. * *

To be useful across a wide range of contexts, this class * provides many adjustable parameters and extensibility hooks. * However, programmers are urged to use the more convenient factory * methods newCachedThreadPool (unbounded thread pool, with * automatic thread reclamation), newFixedThreadPool (fixed * size thread pool), newSingleThreadExecutor (single * background thread for execution of tasks), and * newThreadPerTaskExeceutor (execute each task in a new * thread), that preconfigure settings for the most common usage * scenarios. * * *

This class also maintain some basic statistics, such as the * maximum number of active threads, or the maximum queue length, that * may be useful for monitoring and tuning executors. * *

Tuning guide

*
*
Minimum and maximum pool size
*
ThreadExecutor will * automatically adjust the pool size within the bounds set by * minimumPoolSize and maximumPoolSize. When a new task is submitted, * and fewer than the minimum number of threads are running, a new * thread is created to handle the request, even if other worker * threads are idle. If there are more than the minimum but less than * the maximum number of threads running, a new thread will be created * only if all other threads are busy. By setting minimumPoolSize and * maximumPoolSize to N, you create a fixed-size thread pool.
* *
Keep-alive
*
The keepAliveTime determines what happens to idle * threads. If the pool currently has more than the minimum number of * threads, excess threads will be terminated if they have been idle * for more than the keepAliveTime.
* *
Queueing
*
You are free to specify the queuing mechanism used * to handle submitted tasks. The newCachedThreadPool factory method * uses queueless synchronous channels to to hand off work to threads. * This is a safe, conservative policy that avoids lockups when * handling sets of requests that might have internal dependencies. * The newFixedThreadPool factory method uses a LinkedBlockingQueue, * which will cause new tasks to be queued in cases where all * MaximumPoolSize threads are busy. Queues are sometimes appropriate * when each task is completely independent of others, so tasks cannot * affect each others execution. For example, in an http server. When * given a choice, this pool always prefers adding a new thread rather * than queueing if there are currently fewer than the current * getMinimumPoolSize threads running, but otherwise always prefers * queuing a request rather than adding a new thread. * *

While queuing can be useful in smoothing out transient bursts of * requests, especially in socket-based services, it is not very well * behaved when commands continue to arrive on average faster than * they can be processed. Using a bounded queue implements an overflow * policy which drops requests which cannot be handled due to insufficient * capacity. * * Queue sizes and maximum pool sizes can often be traded off for each * other. Using large queues and small pools minimizes CPU usage, OS * resources, and context-switching overhead, but can lead to * artifically low throughput. If tasks frequently block (for example * if they are I/O bound), a JVM and underlying OS may be able to * schedule time for more threads than you otherwise allow. Use of * small queues or queueless handoffs generally requires larger pool * sizes, which keeps CPUs busier but may encounter unacceptable * scheduling overhead, which also decreases throughput. *

*
Creating new threads
*
New threads are created through the * Callbacks. By default, threads are created simply with * the new Thread(Runnable) constructor, but by overriding * Callbacks.newThread, you can alter the thread's name, * thread group, priority, daemon status, etc. *
*
Before and after intercepts
*
The Callbacks class has * methods which are called before and after execution of a task. * These can be used to manipulate the execution environment (for * example, reinitializing ThreadLocals), gather statistics, or * perform logging. *
*
Blocked execution
*
There are a number of factors which can * bound the number of tasks which can execute at once, including the * maximum pool size and the queuing mechanism used. If you are using * a synchronous queue, the execute() method will block until threads * are available to execute. If you are using a bounded queue, then * tasks will be discarded if the bound is reached. If the executor * determines that a task cannot be executed because it has been * refused by the queue and no threads are available, the * Callbacks.cannotExecute method will be called. *
*
Termination
*
ThreadExecutor supports two shutdown options, * immediate and graceful. In an immediate shutdown, any threads * currently executing are interrupted, and any tasks not yet begun * are returned from the shutdownNow call. In a graceful shutdown, * all queued tasks are allowed to run, but new tasks may not be * submitted. *
*
* * @since 1.5 * @see CannotExecuteHandler * @see Executors * @see ThreadFactory * * @spec JSR-166 * @revised $Date: 2003/05/14 21:30:48 $ * @editor $Author: tim $ * * @fixme If greater control is needed, you can use the * constructor with custom parameters, selectively override * Callbacks, and/or dynamically change tuning * parameters * * @fixme
Brian copied some stuff from dl.u.c for the tuning guide; please * review to make sure that it is still correct * * @fixme
Please check if Brian's statements about queuing and blocking * in the tuning guide are correct. */ public class ThreadPoolExecutor implements ThreadedExecutor { /** * Creates a new ThreadPoolExecutor with the given initial * parameters. It may be more convenient to use one of the factory * methods instead of this general purpose constructor. * * @param minThreads the minimum number of threads to keep in the * pool, even if they are idle. * @param maxThreads the maximum number of threads to allow in the * pool. * @param keepAliveTime when the number of threads is greater than * the minimum, this is the maximum time that excess idle threads * will wait for new tasks before terminating. * @param granularity the time unit for the keepAliveTime * argument. * @param workQueue the queue to use for holding tasks before the * are executed. This queue will hold only the Runnable * tasks submitted by the execute method. * @throws IllegalArgumentException if minThreads, maxThreads, or * keepAliveTime less than zero, or if minThreads greater than * maxThreads. * @throws NullPointerException if workQueue is null */ public ThreadPoolExecutor(int minThreads, int maxThreads, long keepAliveTime, TimeUnit granularity, BlockingQueue workQueue) {} /* Executor implementation. Inherit javadoc from ThreadedExecutor. */ public void execute(Runnable command) {} /* ThreadedExecutor implementation. Inherit javadoc. */ public void setThreadFactory(ThreadFactory threadFactory) { } public ThreadFactory getThreadFactory() { return null; } public void setCannotExecuteHandler(CannotExecuteHandler handler) { } public CannotExecuteHandler getCannotExecuteHandler() { return null; } public BlockingQueue getQueue() { return null; } public void shutdown() {} public List shutdownNow() { return null; } public boolean isShutdown() { return false; } public void interrupt() {} public boolean isTerminated() { return false; } public boolean awaitTermination(long timeout, TimeUnit granularity) throws InterruptedException { return false; } /* @fixme Should any of these be included in ThreadedExecutor interface? */ /** * Sets the minimum allowed number of threads. This overrides any * value set in the constructor. * * @param minThreads the new minimum * @throws IllegalArgumentException if minThreads less than zero */ public void setMinimumPoolSize(int minThreads) {} /** * Returns the minimum allowed number of threads. * * @return the minimum number of threads */ public int getMinimumPoolSize() { return 0; } /** * Sets the maximum allowed number of threads. This overrides any * value set in the constructor. * * @param maxThreads the new maximum * @throws IllegalArgumentException if maxThreads less than zero or * the {@link #getMinimumPoolSize minimum pool size} */ public void setMaximumPoolSize(int maxThreads) {} /** * Returns the maximum allowed number of threads. * * @return the maximum number of threads */ public int getMaximumPoolSize() { return 0; } /** * Sets the time limit for which threads may remain idle before * being terminated. If there are more than the minimum number of * threads currently in the pool, after waiting this amount of * time without processing a task, excess threads will be * terminated. This overrides any value set in the constructor. * @param time the time to wait. A time value of zero will cause * excess threads to terminate immediately after executing tasks. * @param granularity the time unit of the time argument * @throws IllegalArgumentException if msecs less than zero */ public void setKeepAliveTime(long time, TimeUnit granularity) {} /** * Returns the thread keep-alive time, which is the amount of time * which threads in excess of the minimum pool size may remain * idle before being terminated. * * @param granularity the desired time unit of the result * @return the time limit */ public long getKeepAliveTime(TimeUnit granularity) { return 0; } /* Statistics */ /** * Returns the current number of threads in the pool. * * @return the number of threads */ public int getPoolSize() { return 0; } /** * Returns the current number of threads that are actively * executing tasks. * * @return the number of threads */ public int getActiveCount() { return 0; } /** * Returns the maximum number of threads that have ever simultaneously * executed tasks. * * @return the number of threads */ public int getMaximumActiveCount() { return 0; } /** * Returns the number of tasks that have been queued but not yet executed. * * @return the number of tasks */ public int getQueueCount() { return 0; } /** * Returns the maximum number of tasks that have ever been queued * waiting for execution. * * @return the number of tasks */ public int getMaximumQueueCount() { return 0; } /** * Returns the total number of tasks that have been scheduled for execution. * * @return the number of tasks */ public int getCumulativeTaskCount() { return 0; } /** * Returns the total number of tasks that have completed execution. * * @return the number of tasks */ public int getCumulativeCompletedTaskCount() { return 0; } /* @fixme Various CannotExecuteHandler implementations. */ /** * A handler for unexecutable tasks that runs these tasks directly in the * calling thread of the execute method. This is the default * CannotExecuteHandler. */ public class CallerRunsPolicy implements CannotExecuteHandler { /** * Constructs a CallerRunsPolicy. */ public CallerRunsPolicy() { } public boolean cannotExecute(Runnable r, boolean isShutdown) { if (!isShutdown) { r.run(); } return true; } } /** * A handler for unexecutable tasks that throws a CannotExecuteException. */ public class AbortPolicy implements CannotExecuteHandler { /** * Constructs a AbortPolicy. */ public AbortPolicy() { } public boolean cannotExecute(Runnable r, boolean isShutdown) { if (!isShutdown) { throw new CannotExecuteException(); } return true; } } /** * A handler for unexecutable tasks that waits until the task can be * submitted for execution. */ public class WaitPolicy implements CannotExecuteHandler { /** * Constructs a WaitPolicy. */ public WaitPolicy() { } public boolean cannotExecute(Runnable r, boolean isShutdown) { if (!isShutdown) { // FIXME: wait here // FIXME: throw CannotExecuteException if interrupted return false; } return true; } } /** * A handler for unexecutable tasks that silently discards these tasks. */ public class DiscardPolicy implements CannotExecuteHandler { /** * Constructs DiscardPolicy. */ public DiscardPolicy() { } public boolean cannotExecute(Runnable r, boolean isShutdown) { return true; } } /** * A handler for unexecutable tasks that discards the oldest unhandled request. */ public class DiscardOldestPolicy implements CannotExecuteHandler { /** * Constructs a DiscardOldestPolicy. */ public DiscardOldestPolicy() { } public boolean cannotExecute(Runnable r, boolean isShutdown) { if (!isShutdown) { // FIXME: discard oldest here return false; } return true; } } /* * Methods invoked during various points of execution, allowing fine-grained * control and monitoring. */ /** * Method invoked prior to executing the given Runnable in given * thread. This method may be used to re-initialize ThreadLocals, * or to perform logging. * * @param t the thread that will run task r. * @param r the task that will be executed. */ protected void beforeExecute(Thread t, Runnable r) { } /** * Method invoked upon completion of execution of the given * Runnable. If non-null, the Throwable is the uncaught exception * that caused execution to terminate abruptly. * * @param r the runnable that has completed. * @param t the exception that cause termination, or null if * execution completed normally. */ protected void afterExecute(Runnable r, Throwable t) { } /** * Method invoked when the Executor has terminated. Default * implementation does nothing. */ protected void terminated() { } }