在用jdk自带的jvm查看工具(bin/jvisualvm.exe) jvisualvm查看项目的运行状况的时候,发现Thread一只在增加(Thread dump),故进一步了解了一下ThreadPoolExecutor。
ThreadPoolExecutor 的 corePoolSize 的理解:
根据ThreadPoolExecutor的官方doc文档说明:When a new task is submitted in method execute(java.lang.Runnable), and fewer than corePoolSize threads are running, a new thread is created to handle the request, even if other worker threads are idle.
可以看出这个corePoolSize 的意思是说:当外部来了一个execute的请求,如果这时候正在运行状态的线程数 < corePoolSize 的时候,就会创建一个新的Thread去处理。但是需要注意的是,一个ThreadPoolExecutor 在创建之初,是不会立即初始化corePoolSize数量的Thread的,而是通过外部request来一个一个的创建,当达到corePoolSize数目之后,就会维持至少corePoolSize数目的Thread在pool中,哪怕他们都处于空闲状态(idle).
通过例子更好理解一点,下面用ThreadPoolExecutor的子类ScheduledThreadPoolExecutor做例子:
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; public class MyTest { private static AtomicInteger sequenceNumGenerator = new AtomicInteger(); public static void main(String[] args) throws Exception { //pool with corePoolSize 10 ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(10); //print the active thread and total thread num when pool created System.out.println(pool.getActiveCount()); System.out.println(pool.getPoolSize()); //execute 2 task pool.execute(getTask()); pool.execute(getTask()); //print the active thread and total thread num when tasks not finish System.out.println(pool.getActiveCount()); System.out.println(pool.getPoolSize()); //wait to ensure all tasks finish Thread.sleep(3000); //print the active thread and total thread num when all tasks finish System.out.println(pool.getActiveCount()); System.out.println(pool.getPoolSize()); //shutdown thread pool pool.shutdown(); } private static Runnable getTask(){ return new Runnable(){ @Override public void run() { int sequenceNum = sequenceNumGenerator.incrementAndGet(); System.out.println("begin task " + sequenceNum); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("finish task " + sequenceNum); } }; } }
根据结果可以看出:
ThreadPool在初始化的时候,active的thread 和 pool中的thread总数量都是0.也就是说没有初始化任何的thread
执行2个task,并且在task结束之前, active的thread 和 pool中的thread总数量都是2
在执行了2个task之后,并且在task都结束了之后, active的thread 和 pool中的thread总数量分别是0和2
这样就很清楚了,ThreadPoolExecutor的corePoolSize 数量的thread并不是在ThreadPoolExecutor创建的时候就理解初始化的,而是慢慢的通过外部的调用(例如调用execute)来一个一个的创建,最终达到corePoolSize 数量。
下面修改一下corePoolSize,让执行的task数量大于corePoolSize:
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; public class MyTest { private static AtomicInteger sequenceNumGenerator = new AtomicInteger(); public static void main(String[] args) throws Exception { //pool with corePoolSize 10 ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(3); //print the active thread and total thread num when pool created System.out.println(pool.getActiveCount()); System.out.println(pool.getPoolSize()); //execute 2 task pool.execute(getTask()); pool.execute(getTask()); pool.execute(getTask()); pool.execute(getTask()); //print the active thread and total thread num when tasks not finish System.out.println(pool.getActiveCount()); System.out.println(pool.getPoolSize()); //wait to ensure all tasks finish Thread.sleep(4000); //print the active thread and total thread num when all tasks finish System.out.println(pool.getActiveCount()); System.out.println(pool.getPoolSize()); //shutdown thread pool pool.shutdown(); } private static Runnable getTask(){ return new Runnable(){ @Override public void run() { int sequenceNum = sequenceNumGenerator.incrementAndGet(); System.out.println("begin task " + sequenceNum); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("finish task " + sequenceNum); } }; } }
就会发现ThreadPoolExecutor在所以task完成之后,会维持corePoolSize数量的thread在threadpool中,哪怕这些task已经完成工作,处于空闲状态(idle)