线程池中重要的两张图:
1、线程执行流程图:
任务被提交到线程池,会先判断当前线程数量是否小于corePoolSize,如果小于则创建线程来执行提交的任务,否则将任务放入workQueue队列,如果workQueue满了,则判断当前线程数量是否小于maximumPoolSize,如果小于则创建线程执行任务,否则就会调用handler,以表示线程池拒绝接收任务。
2、worker、task执行流程:
从execute方法开始,Worker使用ThreadFactory创建新的工作线程,runWorker通过getTask获取任务(getTask()方法从阻塞队列中取任务,超时时间及定义线程池中的空闲时间),然后执行任务,如果getTask返回null,进入processWorkerExit方法,整个线程结束。
改前:
int pageSize = 20000;
ThreadPoolExecutor exec = new ThreadPoolExecutor(
5,
10,
5L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(1),
new SdmsThreadFactory("insertSalesDataToEsThread"),
new ThreadPoolExecutor.CallerRunsPolicy()
);
修改后:
int pageSize = 10000;
ThreadPoolExecutor exec = new ThreadPoolExecutor(
8,
30,
1L, TimeUnit.MINUTES,
new LinkedBlockingQueue<>(50),
new SdmsThreadFactory("insertSalesDataToEsThread"),
new ThreadPoolExecutor.CallerRunsPolicy()
);
es 数据同步,线程优化:
1、批量处理数据量,20000->10000,es 同步更新时间缩短;
2、核心线程数,5->8,充分利用内核数(8核);
3、最大线程数,10->30
4、队列长度,1->50,核心线程数占满后,新增的任务加入到队列中,充分利用线程池的作用(getTask()),不用大量新增新的线程
(速度慢:1、大量新增线程,未利用到线程池的作用;2、内存中老年代对象大量存在,很难回收,)
cmd 查看线程执行情况:
jps:进程id
jconsole: 打开java监视和管理控制台
jmap -histo:live 15840 | more : 查看实例情况
jmap -dump:live,format=b,file=d:\dump\heap.hprof “pid” : 使用 jmap 命令生成 dump 文件