zoukankan      html  css  js  c++  java
  • java多线程 ThreadPoolExecutor 策略的坑

       无论是使用jdk的线程池ThreadPoolExecutor 还是spring的线程池ThreadPoolTaskExecutor 都会使用到一个阻塞队列来进行存储线程任务。

       当线程不够用时,则将后续的任务暂存到 阻塞队列中,等待有空闲线程来进行。

      当这个阻塞队列满了的时候,会出现两种情况

       正在运行的线程数量小于 maximumPoolSize,那么还是要创建线程运行这个任务;

       正在运行的线程数量大于或等于 maximumPoolSize,那么线程池会通过一个策略进行对后续的任务进行处理。

    四种策略

    ThreadPoolExecutor.AbortPolicy()  抛出java.util.concurrent.RejectedExecutionException异常 
    ThreadPoolExecutor.CallerRunsPolicy() 重试添加当前的任务,他会自动重复调用execute()方法 
    ThreadPoolExecutor.DiscardOldestPolicy() 抛弃旧的任务 
    ThreadPoolExecutor.DiscardPolicy() 抛弃当前的任务 

    其他很容易看出来,最近踩了一个ThreadPoolExecutor.CallerRunsPolicy()的坑。

    情景是这样的:我需要通过线程进行创建长连接,当开启了15个线程的是,线程池最大即达到了maximumPoolSize的数量的时候,继续增大请求量,会无缘无故的多出来

    一个长连接,由于有负载均衡,导致了很多请求无法从长连接中得到。

    经过很长时间的测试,最终发现了是ThreadPoolExecutor.CallerRunsPolicy()策略导致的。

    这个测试是当你的线程数达到最大,阻塞队列也满了的时候,之后的任务会强制先执行,但是没有了线程谁来执行呢,这个策略会强制中断主线程进行执行这个任务。

    即是说,当我的量上来,线程池不够用的时候,中断了我的主线程,主线程没有长连接,就建立了一个新的长连接,那边进行了负载均衡,但是这边不会在进行主线程了,

    导致很多请求接收不到。

    假设队列大小为 10,corePoolSize 为 3,maximumPoolSize 为 6,那么当加入 20 个任务时,执行的顺序就是这样的:首先执行任务 1、2、3,然后任务 4~13 被放入队列。这时候队列满了,任务 14、15、16 会被马上执行,最终顺序是:1、2、3、14、15、16、4、5、6、7、8、9、10、11、12、13。

    踩坑完毕

    最终做法:

    换成ThreadPoolExecutor.DiscardPolicy()策略,还是从已经建立的连接中进行 的到请求,不要继续创建连接。

  • 相关阅读:
    获取窗口句柄,并向窗口发送自定义消息
    双向链表总结
    循环链表总结
    顺序队列总结
    链式栈总结
    顺序栈的总结
    链式队列总结
    源码网址
    通用型动态数组的总结
    单链表的链式存储总结
  • 原文地址:https://www.cnblogs.com/lic309/p/4564507.html
Copyright © 2011-2022 走看看