一起使用Spring @Scheduled和@Async

use*_*833 11 memory spring scheduled-tasks

这是我的用例.

遗留系统更新数据库队列表QUEUE.

我想要一个计划的重复作业 - 检查队列的内容 - 如果表中有行它会锁定行并做一些工作 - 删除队列中的行

如果上一个作业仍在运行,则将创建一个新线程来完成工作.我想配置最大并发线程数.

我正在使用Spring 3,我目前的解决方案是执行以下操作(使用1毫秒的fixedRate来使线程基本连续运行)

@Scheduled(fixedRate = 1)
@Async
public void doSchedule() throws InterruptedException {
    log.debug("Start schedule");
    publishWorker.start();
    log.debug("End schedule");
}

<task:executor id="workerExecutor" pool-size="4" />
Run Code Online (Sandbox Code Playgroud)

这直接创建了4个线程,并且线程正确地共享了队列中的工作负载.但是,当线程需要很长时间才能完成时,我似乎得到了内存泄漏.

java.util.concurrent.ThreadPoolExecutor @ 0xe097b8f0                              |              80 |   373,410,496 |     89.74%
|- java.util.concurrent.LinkedBlockingQueue @ 0xe097b940                          |           48 |   373,410,136 |     89.74%
|  |- java.util.concurrent.LinkedBlockingQueue$Node @ 0xe25c9d68  
Run Code Online (Sandbox Code Playgroud)

所以

1:我应该一起使用@Async和@Scheduled吗?

2:如果没有,那么我怎么用春天来达到我的要求呢?

3:如何在其他线程忙时才创建新线程?

谢谢大家!

编辑:我认为工作队伍变得无限长......现在正在使用

    <task:executor id="workerExecutor"
    pool-size="1-4"
    queue-capacity="10" rejection-policy="DISCARD" />
Run Code Online (Sandbox Code Playgroud)

将报告结果

raj*_*vas 1

//using a fixedRate of 1 millisecond to get the threads to run basically continuously
@Scheduled(fixedRate = 1)
Run Code Online (Sandbox Code Playgroud)

当您使用时,@Scheduled将创建一个新线程,并将doSchedule 以 1 毫秒的指定固定速率调用方法。当您运行应用程序时,您已经可以看到 4 个线程竞争 QUEUE 表,并且可能出现死锁。

通过获取线程转储来调查是否存在死锁。 http://helpx.adobe.com/cq/kb/TakeThreadDump.html

@Async 注释在这里没有任何用处。

实现此目的的更好方法是通过实现 runnable 并将类传递给所需数量的线程,将类创建为线程TaskExecutor

使用 Spring 线程和 TaskExecutor,我如何知道线程何时完成?

另请检查您的设计,它似乎没有正确处理同步。如果上一个作业正在运行并持有该行的锁,则您创建的下一个作业仍将看到该行,并等待获取该特定行的锁。