线程池的作用:一方面能支持多个异步操作,尤其能提高性能。另一方面是对池中的线程进行管理。
Thread pools address two different problems: 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 when executing a collection of tasks.
Each ThreadPoolExecutor also maintains some basic
statistics, such as the number of completed tasks.
线程池的状态变化:
RUNNING: Accept new tasks and process queued tasks
SHUTDOWN: Don't accept new tasks, but process queued tasks
STOP: Don't accept new tasks, don't process queued tasks,
and interrupt in-progress tasks
TERMINATED: Same as STOP, plus all threads have terminated
RUNNING -> SHUTDOWN
On invocation of shutdown(), perhaps implicitly in finalize()
(RUNNING or SHUTDOWN) -> STOP
On invocation of shutdownNow()
SHUTDOWN -> TERMINATED
When both queue and pool are empty
STOP -> TERMINATED
When pool is empty
线程池能对里面的线程进行动态调整
When a new task is submitted in method and fewer than corePoolSize threads
are running, a new thread is created to handle the request, even if
other worker threads are idle. If there are more than
corePoolSize but less than maximumPoolSize threads running, a new
thread will be created only if the queue is full. By setting
corePoolSize and maximumPoolSize the same, you create a fixed-size
thread pool. By setting maximumPoolSize to an essentially unbounded
value such as Integer.MAX_VALUE, you allow the pool to
accommodate an arbitrary number of concurrent tasks. Most typically,
core and maximum pool sizes are set only upon construction, but they
may also be changed dynamically 。
如果池中的线程长时间没用到,则为了节约资源,会终止它。
If the pool currently has more than corePoolSize threads,
* excess threads will be terminated if they have been idle for more
* than the keepAliveTime
每个线程池都维护一个任务队列,该队列的实现有3种,一种是无限容量的,LinkedBlockingQueue,这个比较适合大并发的,另一种是有限容量的 ArrayBlockingQueue,但是这个比较容易出现长的时间延迟,一种办法就是线程池中线程的数量要多些。还有一种队列,则是虚队列SynchronousQueue,它不会真正有入队,出队操作,它只负责传输,入队的时候,如果当时没有线程空闲的话,则会创造一个。
Executors.newCachedThreadPool()工厂就采用的这种机制。
拒绝任务 一种是当线程池处于关闭的状态,另一种是队列容量已满,而且没有多余的线程
可以创建去接收任务。居然可以自己这个线程去执行这个任务,如果线程池的线程都在运行的时候,但是
这个会影响任务提交。还有一种则是重新提交,也即多次提交。最简单的则是放弃这个任务。当然也有其他策略来处理这个
当提交任务是,线程池都已满,并且工作队列也无空闲位置的情况下,ThreadPoolExecutor会执行reject操作,JDK提供了四种reject策略,包括AbortPolicy(直接抛RejectedException Exception),CallerRunsPolicy(提交任务线程自己执行,当然这时剩余任务也将无法提交),DiscardOldestPolicy(将线程池的workQueue任务队列里面最老的任务剔除,将新任务丢入),DiscardPolicy(无视,忽略此任务,并且立即返回).实例化ThreadPoolExecutor时,如果不指定任何饱和策略,默认将使用AbortPolicy.
New tasks submitted in method will be rejected when the
Executor has been shut down, and also when the Executor uses finite
bounds for both maximum threads and work queue capacity, and is
saturated.
/**
* Timeout in nanoseconds for idle threads waiting for work.
* Threads use this timeout when there are more than corePoolSize
* present or if allowCoreThreadTimeOut. Otherwise they wait
* forever for new work.
*/
private volatile long keepAliveTime;
/**
* If false (default) core threads stay alive even when idle. If
* true, core threads use keepAliveTime to time out waiting for
* work.
*/
private volatile boolean allowCoreThreadTimeOut;
/**
* Core pool size, updated only while holding mainLock, but
* volatile to allow concurrent readability even during updates.
*/
private volatile int corePoolSize;
/**
* Maximum pool size, updated only while holding mainLock but
* volatile to allow concurrent readability even during updates.
*/
private volatile int maximumPoolSize;
/**
* Current pool size, updated only while holding mainLock but
* volatile to allow concurrent readability even during updates.
*/
private volatile int poolSize;
/**
* Handler called when saturated or shutdown in execute.
*/
private volatile RejectedExecutionHandler handler;
自己全部对线程池进行控制,如可以自己实现拒绝策略等
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}