一个线程池通常有如下几部分组成,核心线程池,非核心线程池和工作队列。
核心线程池中的线程会一直存在,空闲时不会被回收;非核心线程池中的线程在空闲一定时间后可能被回收;工作队列存放线程池中暂时无法处理执行的任务。
Java线程池说明
Java定义了Executor接口并在该接口中定义了execute( )用于执行一个线程任务,然后通过ExecutorService实现Executor接口并执行具体的线程操作。ExecutorService接口有多个实现类可用于创建不同的线程池。
newCachedThreadPool
newCachedThreadPool用于创建一个缓存线程池。之所以叫缓存线程池,是因为它在创建新线程时,如果有可重用的线程,则重用他们,否则重新创建一个新的线程并将其添加到线程池中。对于执行时间很短的任务惹眼,newCachedThreadPool线程池能很大程度地重用线程进而提高系统的性能。
在线程池的keepAliveTime时间超过默认的60秒后,该线程会被终止并从缓存中移除,因此在没有线程任务运行时,newCachedThreadPool将不会占用系统的线程资源。
在创建线程时需要执行申请CPU和内存、记录线程状态、控制阻塞等多项工作,复杂且耗时。因此,在有执行时间很短的大量任务需要执行的情况下,newCachedThreadPool能够很好地复用运行中的线程(任务已经完成但未关闭的线程)资源来提高系统的运行效率。
/**
* 创建一个线程池,根据须要创建多个线程,
* 但是会重复使用之前创建好的且已经空闲的线程资源。
* 这个线程池通常会提高执行许多短暂异步任务的程序的性能。
* 调用execute()方法将重用以前构造的线程(如果可用)。
* 如果没有可用的线程存在, 则会创建一个新的线程,并将其添加到线程池中。
* 如果线程60秒没有被使用,那么会被终结掉并从线程池中移除。
* 因此,长时间保持闲置的线程池不会占用资源.
* 可以使用ThreadPoolExecutor构造方法,创建具有相似属性不同细节的线程池
*
* @return the newly created thread pool
*/
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
根据newCachedThreadPool源代码可以看到,newCachedThreadPool线程池中固定的核心线程数量为0,非核心线程数量不做限制,最大数量可达Integer.MAX_VALUE。线程池空闲线程超时为60秒,即空闲线程在60秒内没有新的任务执行,该线程就会释放掉。SynchronousQueue队列是一个没有存储空间的阻塞队列,这意味着只要有请求到来,就必须要有一条工作线程处理他,如果当前没有空闲的线程,那么就会再创建一条新的线程出来。
newFixedThreadPool
newFixedThreadPool用于创建一个固定线程数量的线程池,并将线程资源存放在队列中循环使用。在newFixedThreadPool线程池中,若处于活动状态的线程数量大于等于核心线程池的数量,则新提交的任务将在阻塞队列中排队,直到有可用的线程资源。
/**
* 创建一个重复使用固定线程数量的线程池来操作无界共享任务队列中任务。
* 在任何时候,最多只有nThreads数量的线程处于激活处理任务状态。
* 如果有任务在所有线程都处于活跃执行任务时提交,
* 那他们将被添加到等待队列中,直到有线程空闲可用为止.
* 如果任何线程在关闭之前的执行任务期间发生故障而终止,
* 如果须要则会有一个新的任务产生,继续执行任务。
* 线程池中的线程会一直存在,直到被显示shutdown.
*
* @param nThreads 线程池中线程数量
* @return 先创建的线程池
* @throws IllegalArgumentException if {@code nThreads <= 0}
*/
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
newFixedTh