当前位置: 移动技术网 > IT编程>开发语言>Java > 使用线程池仍同步处理请求问题

使用线程池仍同步处理请求问题

2020年07月17日  | 移动技术网IT编程  | 我要评论

发现:

线上一个使用线程池处理任务的RPC接口超时:

@Resource
private ThreadPoolTaskExecutor threadPool;

@Override
    public Response rpcMethod(Request request) throws TException {
    	//这里使用匿名内部类方式创建Runnable类型的线程
    	 threadPool.submit(() -> myMethod(request));
	}

排查

上面接口在日志里显示耗时3s, 按理收到请求后就使用线程池中的其他线程处理了,没有等待返回结果,接口应该很快,这里并没有使用Callable类型获取Future结果,所以理论上不会发生阻塞。
排查trace日志,发现显示这次整个调用链将myMethod内部的调用都打印出来,时间也都算在rpcMethod内了,说明线程池没有起作用,同步处理的这次请求
在这里插入图片描述

原因

查看线程池配置如下:

 <!-- 多线程配置 -->
    <bean id="threadPool" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
        <!-- 线程池的前缀 -->
        <property name="threadNamePrefix" value="myThread"/>
        <!-- 核心线程数 -->
        <property name="corePoolSize" value="5" />
        <!-- 最大线程数 -->
        <property name="maxPoolSize" value="10" />
        <!-- 队列最大长度-->
        <property name="queueCapacity" value="500" />
        <!-- 线程池维护线程所允许的空闲时间,默认为60s -->
        <property name="keepAliveSeconds" value="30" />
        <!-- 核心线程超时退出,默认为false -->
        <property name="allowCoreThreadTimeOut" value="true" />
        <!-- 线程池对拒绝任务(无线程可用)的处理策略,目前只支持AbortPolicy、CallerRunsPolicy;默认为后者 -->
        <property name="rejectedExecutionHandler">
            <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />
        </property>
    </bean>

当时的并发请求量为1000,在线程池中的处理为:

  • 如果运行的线程少于corePoolSize-5,则创建新线程来处理任务,即使线程池中的其他线程是空闲的 (这里前5个请求被放进阻塞队列中)

  • 如果线程池中的线程数量大于等于corePoolSize-5 且小于 maximumPoolSize-10,则只有当workQueue-500 满时才创建新的线程去处理任务。 (这里同时到达的第6-506个请求被放进阻塞队列中)

  • 如果设置的corePoolSize 和 maximumPoolSize相同,则创建的线程池的大小是固定的,这时如果有新任务提交,若workQueue未满,则将请求放入workQueue中,等待有空闲的线程去从workQueue中取任务并处理;

  • 如果workQueue已经满了,会创建新线程处理新请求 (这里第507个到512个请求新建了5个线程处理) 直到线程数到达maximumPoolSize-10, 512后面的请求,由于最大线程数和阻塞队列都有任务了,则通过handler所指定的策略来处理任务
    线程池任务的优先级:corePoolSize>queueCapacity>maxPoolSize
    配置里制定的策略为CallerRunsPolicy:使用线程调用者所在的线程来执行任务
    在这里插入图片描述
    线程池提供了4种策略:

  • AbortPolicy:直接抛出异常,这是默认策略;

  • CallerRunsPolicy:用调用者所在的线程来执行任务;

  • DiscardOldestPolicy:丢弃阻塞队列中靠最前的任务,并执行当前任务;

  • DiscardPolicy:直接丢弃任务;

参考:
ThreadPoolExecutor里面4种拒绝策略–CallerRunsPolicy
Java多线程-线程池ThreadPoolExecutor的submit返回值Future

本文地址:https://blog.csdn.net/weixin_42655186/article/details/107359954

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网