以前一直没有深刻准确的理解ThreadPoolExecutor的线程调度的规则,抽时间深入测试了下,总结记录分享下:
ThreadPoolExecutor(int corePoolSize, ? ? ? ? ? ? ? ? ? ?int maximumPoolSize, ? ? ? ? ? ? ? ? ? ?long keepAliveTime, ? ? ? ? ? ? ? ? ? ?TimeUnit unit, ? ? ? ? ? ? ? ? ? ?BlockingQueue<Runnable> workQueue) |
---|
Params: corePoolSize – the number of threads to keep in the pool, even if they are idle, unless allowCoreThreadTimeOut is set maximumPoolSize – the maximum number of threads to allow in the pool keepAliveTime – when the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks before terminating. unit – the time unit for the keepAliveTime argument workQueue – the queue to use for holding tasks before they are executed. This queue will hold only the Runnable tasks submitted by the execute method. |
先说结论:corePoolSize-->workQueue-->maximumPoolSize |
---|
当n个请求过来的时候,线程池是这么处理的: 当n<=corePoolSize时:直接使用核心线程; 当n>corePoolSize时:先将核心线程占满,剩余的n-corePoolSize个请求将进入workQueue(阻塞队列),这里又分以下情况: --------当n-corePoolSize<=workQueue的最大容量,全部进入workQueue; --------当n-corePoolSize>workQueue的最大容量,请求先塞满workQueue,多余的请求n-corePoolSize-workQueue将根据maximumPoolSize-corePoolSize的余量开辟新的线程响应请求, --------直到达到maximumPoolSize,停止创建,超出的请求(n-maximumPoolSize-workQueue)直接被拒绝 | 来个demo:corePoolSize=3;maximumPoolSize=5;workQueue=5; (1)当n<=3:直接占用核心线程池; (2)当n=4~8:3个核心线程占满、1个请求进入workQueue; (3)当n=9~10:3个核心线程占满、5个请求进入workQueue、剩下的请求新开线程响应; (4)当n>10:3个核心线程占满、5个请求进入workQueue、2个请求被新开线程响应、其余的请求直接拒绝 | 测试class: import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ThreadPoolTest {
public static void main(String[] args) {
LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(5);
ThreadPoolExecutor executor = new ThreadPoolExecutor(3,
5, 60 * 1000, TimeUnit.MILLISECONDS, queue);
for (int i = 1; i < 12; i++) {
//System.out.println("第"+i+"个线程准备启动");
final int number = i;
try {
executor.execute(new Runnable() {
@Override
public void run() {
System.out.println("thread start : " + number + " 时间:" + System.currentTimeMillis()/1000);
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("--------------------------");
System.out.println("getCorePoolSize: "+executor.getCorePoolSize());
System.out.println("getActiveCount: "+executor.getActiveCount());
System.out.println("getPoolSize: "+executor.getPoolSize());
System.out.println("getQueue: "+executor.getQueue().size());
System.out.println("getMaximumPoolSize: "+executor.getMaximumPoolSize());
System.out.println("--------------------------");
}
} | 运行结果:3个corePool(1/2/3)、5个queue(4/5/6/7/8)、2个临时开辟(9/10)、1个拒绝(11) (感兴趣的可以修改三个核心参数,模拟其他case) thread start : 2 ?时间:1649817402 thread start : 1 ?时间:1649817402 thread start : 3 ?时间:1649817402 thread start : 10 ?时间:1649817402 thread start : 9 ?时间:1649817402 -------------------------- getCorePoolSize: 3 getActiveCount: 5 getPoolSize: 5 getQueue: 5 getMaximumPoolSize: 5 -------------------------- java.util.concurrent.RejectedExecutionException: Task com.jd.xz.idata.service.utils.ThreadPoolTest$1@573fd745 rejected from java.util.concurrent.ThreadPoolExecutor@15327b79[Running, pool size = 5, active threads = 5, queued tasks = 5, completed tasks = 0] ? ? at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063) ? ? at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830) ? ? at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379) ? ? at com.jd.xz.idata.service.utils.ThreadPoolTest.main(ThreadPoolTest.java:17) thread start : 4 ?时间:1649817407 thread start : 7 ?时间:1649817407 thread start : 5 ?时间:1649817407 thread start : 8 ?时间:1649817407 thread start : 6 ?时间:1649817407 |
|