在下面的 Spring Integration 文档的 7.1.7 异步轮询部分中,解释了如果 Poller 和 TaskExecutor 不协调可能会发生内存泄漏。但我不明白。
<int:service-activator input-channel="publishChannel" ref="myService">
<int:poller receive-timeout="5000" task-executor="taskExecutor" fixed-rate="50"/>
</int:service-activator>
<task:executor id="taskExecutor" pool-size="20" queue-capacity="20"/>
上面的配置演示了其中一种不协调的配置。
即使所有线程都被阻塞等待新消息到达或超时到期,轮询器仍会继续调度新任务。假设有 20 个线程执行 5 秒超时的任务,它们将以每秒 4 个的速率执行(5000/20 = 250ms)。但是,新任务以每秒 20 个的速度被调度,因此任务执行器中的内部队列将以每秒 16 个的速度增长(当进程空闲时),所以我们基本上有内存泄漏。
处理此问题的方法之一是将 > 任务执行器的 queue-capacity 属性设置为 0。
有人可以详细说明一下。
以下是我对上述代码的理解:
pool-size 为 20 - 因此将执行 20 个线程。
接收超时为 5 秒:因此 20 个线程将有 5 秒的时间来完成任务。
固定速率为 50 毫秒 - 因此新任务以每秒 20 个的速率进行调度。
我有几个问题:
Q. 如果执行 20 个线程的时间超过 5 秒会怎样?
Q. 在文档中,它所说的任务将以每秒 4 个的速度执行。但是,有些任务可能会在不到 4 秒的时间内运行,有些则需要更多时间。
Q. 它是如何导致内存泄漏的?如果没有可用的线程和队列,Executor 会根据拒绝策略拒绝它。
问:将 queue-capacity 设置为 0 有何帮助?根据我的理解,如果所有线程都忙,那么 Executor 会将它们放入队列中,直到达到队列容量。