线程池创建线程超时

本文探讨了Java线程池在高并发环境下创建线程及上下文切换对性能的影响。当核心线程数不为0时,线程池会持续创建核心线程来处理任务。在任务量超出核心线程后,线程池会创建更多线程直至达到最大线程数。线程的启动到实际执行存在一定的延迟,主要是由于CPU的上下文切换。通过预启动所有核心线程(`executorServer.prestartAllCoreThreads();`)可以显著减少延迟,测试显示这能将延迟降低到3ms左右。Hutool库的`ThreadUtil.execAsyn`方法也能改善性能,但相比预启动核心线程仍有9-14ms的开销。
摘要由CSDN通过智能技术生成
 
  1. ExecutorService executorServer = xxxxxx.getThreadPool();

  2.  
  3. Future future = executorServer.submit(new xxxxxxx(Param, funcId));

  4.  
  5.  
  6. Object obj = future.get(100, TimeUnit.MILLISECONDS); //总超时时间设置

  7.  

其中,future.get是从开始进行get方法时进行计算的时间,非future生成开始计算的,即什么时候get什么时候开始计时。

线程池从生成线程,如果核心线程不为0,则有任务时一直生成核心线程,直至到核心线程,之后开始方队列中,最后任务多就开始开辟新线程到最大线程数。

 

执行任务时,首先线程池开辟线程,之后 线程start( execute方法->addWorker-->t.start())后开始执行call方法。但从.start 到 执行call方法,需要CPU进行线程的上下文切换。 可以根据重写的

ThreadPoolExecutor方法来跟踪。

在高并发下,如果线程池不加 executorServer.prestartAllCoreThreads();

则在线程为1500的并发下,即新创建线程start状态为NEW,真正运行时为RUNNABLE(start后),到call真正的调用会耗时,因CPU切换。

如不加,则会有12-160多ms的消耗,

如果加上prestartAllCoreThreads()则性能会好很多,最大从start到call才3ms.

同时,如使用hutool-all-5.3.8.jar的ThreadUtil.execAsyn方法效果也比较好,但没有restartAllCoreThreads()这个好,测试效果有9-14ms的消耗。

 

 
  1. public static ThreadPoolExecutor getThreadPool() {

  2. if (executorServer == null || executorServer.isShutdown() || executorServer.isTerminated()) {

  3. synchronized (JzPreCheckUtil.class) {

  4. if (executorServer == null || executorServer.isShutdown() || executorServer.isTerminated()) {

  5. XxxConfig.isJzPrecheckEnabled(); //加载相关配置

  6. log.info("corePoolSize="+XxxConfig.corePoolSize+" maximumPoolSize="+XxxConfig.maximumPoolSize+" keepAliveTime="+XxxConfig.keepAliveTime);

  7. ThreadFactory threadFactory = new ThreadFactory() {

  8. @Override

  9. public Thread newThread(Runnable r) {

  10. long t1=System.currentTimeMillis();

  11. String threadName="jzThreadPool" + r.hashCode();

  12. Thread newThread=new Thread(r, threadName);

  13. long t2=System.currentTimeMillis();

  14. log.info("创建线程="+threadName+" t1="+t1+" t2="+t2+" 时间差="+(t2-t1));

  15. return newThread;

  16. }

  17. };

  18.  
  19.  
  20. executorServer = new ThreadPoolExecutor(XxxConfig.corePoolSize, XxxConfig.maximumPoolSize, XxxConfig.keepAliveTime, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(),threadFactory);

  21. executorServer.prestartAllCoreThreads();

  22.  
  23. log.info("prestartAllCoreThreads 之后="+executorServer.getQueue().size()+" 线程活着的数量="+executorServer.getActiveCount()+

  24. " 核心线程="+executorServer.getCorePoolSize()+" 最大线程="+executorServer.getMaximumPoolSize()+

  25. " 线程数="+executorServer.getPoolSize());

  26.  
  27. }

  28. }

  29. }

  30. log.info("queue 长度 后="+executorServer.getQueue().size()+" 线程活着的数量="+executorServer.getActiveCount()+

  31. " 核心线程="+executorServer.getCorePoolSize()+" 最大线程="+executorServer.getMaximumPoolSize()+

  32. " 线程数="+executorServer.getPoolSize());

  33.  
  34. return executorServer;

  35. }

 
  1. @Override

  2. public Object call() throws Exception {

  3.  
  4. xxx

  5. return out;

  6.  
  7. }

 

 

重写

ThreadPoolExecutor参考:
 
  1. package com.stock.framework.precheck.test2;

  2.  
  3. import com.stock.framework.jzprecheck.JzConfig;

  4. import org.slf4j.Logger;

  5.  
  6. import java.lang.reflect.Constructor;

  7. import java.lang.reflect.Field;

  8. import java.lang.reflect.InvocationTargetException;

  9. import java.lang.reflect.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值