ThreadPoolExecutor :: Executor

时间:2016-07-08 05:24:20

标签: java spring spring-jms threadpoolexecutor

我的应用程序是通过Jms MessageListener类读取消息,并且在某些时候它正在抛出 TaskRejectedException 。我知道大多数人会说 maxPoolSize 超出了线程数,队列也已满。

但是我发现了一些事情。发送到MessageListener类从中获取消息的队列的消息数是10353,而threadPoolExecutor的spring属性如下:

<bean id="ticketReaderThreadPool" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" scope="singleton" destroy-method="destroy">
    <property name="corePoolSize" value="10" />
    <property name="maxPoolSize" value="150" />
    <property name="queueCapacity" value="11000" />
</bean>

现在据我所知,maxPoolSize足以处理这些请求。因此,如果你们中的任何人可以提供除maxPoolSize漏洞之外的原因,那么请这样做。

我们现在第二次面临这个问题,之前我们已经尝试过增加maxPoolSize,但在15天之后我们又遇到了这个例外,每天大约需要5000到8000次。

更新

这是异常的完整堆栈跟踪:

  

从队列/处理消息中读取时发生一般异常   org.springframework.core.task.TaskRejectedException:Executor [java.util.concurrent.ThreadPoolExecutor@408b9775]不接受任务:com.batman.rapid.rapidserver.sla.TicketHandler@1be5e598           在org.springframework.scheduling.concurrent.ThreadPoolTask​​Executor.execute(ThreadPoolTask​​Executor.java:244)           在com.batman.rapid.rapidserver.sla.JmsTicketReceiver.onMessage(JmsTicketReceiver.java:58)           在org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:560)           在org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:498)           在org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:467)           在org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:325)           在org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:263)           at org.springframework.jms.listener.DefaultMessageListenerContainer $ AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1058)           at org.springframework.jms.listener.DefaultMessageListenerContainer $ AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1050)           在org.springframework.jms.listener.DefaultMessageListenerContainer $ AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:947)           在java.lang.Thread.run(Thread.java:662)   引起:java.util.concurrent.RejectedExecutionException           at java.util.concurrent.ThreadPoolExecutor $ AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1774)           at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:768)           at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:656)           在org.springframework.scheduling.concurrent.ThreadPoolTask​​Executor.execute(ThreadPoolTask​​Executor.java:241)           ......还有10个

这是相关代码:

if (message instanceof TextMessage)
{
    textMessage = (TextMessage) message;
    ticketReaderThreadPool.execute(new TicketHandler(textMessage.getText()));
}

以下是所要求的配置:

                                                           

    <!-- End of JMS Queue Support -->

    <bean id="ticketReaderThreadPool" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" scope="singleton" destroy-method="destroy">
    <property name="corePoolSize" value="10" />
    <property name="maxPoolSize" value="150" />
    <property name="queueCapacity" value="11000" />
</bean>

    <bean id="notificationThreadPool" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" scope="singleton" destroy-method="destroy">
            <property name="corePoolSize" value="10" />
            <property name="maxPoolSize" value="100" />
            <property name="queueCapacity" value="10000" />
    </bean>

    <bean id="notificationManager" class="com.batman.rapid.rapidserver.sla.scheduler.NotificationManager" scope="singleton">
            <property name="defaultPercent" value="80"></property>
    </bean>

    <bean id="dbUpdateThreads" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" scope="singleton" destroy-method="destroy">
            <property name="corePoolSize" value="1" />
            <property name="maxPoolSize" value="100" />
            <property name="queueCapacity" value="10000" />
    </bean>

1 个答案:

答案 0 :(得分:1)

不确定究竟是什么原因。但是我强烈地感觉到,最大消息数可能会超出您设置的maxqueueCapacity。但是,您使用的不同方法与JMS的一般用法不同。通常在DefaultMessageListener中,我们配置Max-consumer的数量,以并行处理异步处理。基于服务器资源,我们配置服务器可以处理的最大消费者

但是在您的情况下,从DefaultMessageListener中读取消息并生成新线程并在新线程中执行业务逻辑。由于消息侦听器读取比业务逻辑更快,因此任务在线程任务队列中累积。

我建议重新接近你当前的实现。因为它不支持交易。我的意思是当服务器崩溃时,任务中的所有待处理消息处理都将被终止/丢失,并且由于您将设置auto-ack,因此该消息将从队列中删除。其他问题如设置线程队列的手动限制等。

最后回到你的问题,你可以快速检查你设置的150个线程中是否有锁