在用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)