Spring 应用程序的计时器线程不断增加

Spring application's timer threads keep increasing

我有一些 Java 应用程序使用 Spring Batch。我有一个 table 用作队列,其中包含有关客户端请求的作业的信息(当客户端请求执行任务时,将向该队列添加一行)。

在我的一个 类 中,一个 while 循环是 运行 直到有人停用了一些标志:

    protected void runJobLaunchingLoop() {
        while (!isTerminated()) {
            try {
                if (isActivated()) {
                    QueueEntryDTO queueEntry = dequeueJobEntry();
                    launchJob(queueEntry);
                }
            }
            catch (EmptyQueueException ignored) {}
            catch (Exception exception) {
                logger.error("There was a problem while de-queuing a job ('" + exception.getMessage() + "').");
            }
            finally {
                pauseProcessor();
            }
        }
    }

pauseProcessor() 方法调用 Thread.sleep()。当我 运行 这个应用程序在 Docker 容器中时,应用程序的线程数 运行 似乎在不断增加。线程的名称为“Timer-X”,其中 X 是一些自动递增的整数。

我查看了其中一个的堆栈跟踪:

    "Timer-14" - Thread t@128
   java.lang.Thread.State: WAITING
    at java.base@11.0.6/java.lang.Object.wait(Native Method)
    - waiting on <25e60c31> (a java.util.TaskQueue)
    at java.base@11.0.6/java.lang.Object.wait(Unknown Source)
    at java.base@11.0.6/java.util.TimerThread.mainLoop(Unknown Source)
    - locked <25e60c31> (a java.util.TaskQueue)
    at java.base@11.0.6/java.util.TimerThread.run(Unknown Source)

   Locked ownable synchronizers:
    - None

知道这可能是什么原因吗?我不确定,但如果我不 运行 容器中的应用程序而是来自 IntelliJ 的本地应用程序,那么问题似乎不会发生。我不确定,因为有时线程数开始增加需要一段时间。


编辑:一些相关代码...

protected QueueEntryDTO dequeueJobEntry() {
        Collection<QueueEntryDTO> collection = getQueueService().dequeueEntry();
        if (collection.isEmpty())
            throw new EmptyQueueException();
        return collection.iterator().next();
    }

@Transactional
    public Collection<QueueEntryDTO> dequeueEntry() {
        Optional<QueueEntry> optionalEntry = this.queueEntryDAO.findTopByStatusCode(QueueStatusEnum.WAITING.getStatusCode());
        if (optionalEntry.isPresent()) {
            QueueEntry entry = (QueueEntry)optionalEntry.get();
            QueueEntry updatedEntry = this.saveEntryStatus(entry, QueueStatusEnum.PROCESSING, (String)null);
            return Collections.singleton(this.queueEntryDTOMapper.toDTO(updatedEntry));
        } else {
            return new ArrayList();
        }
    }

private void pauseProcessor() {
        try {
            Long sleepDuration = generalProperties.getQueueProcessingSleepDuration();
            sleepDuration = Objects.requireNonNullElseGet(
                    sleepDuration,
                    () -> Double.valueOf(Math.pow(2.0, getRetries()) * 1000.0).longValue());
            Thread.sleep(sleepDuration);
            if (getRetries() < 4)
                setRetries(getRetries() + 1);
        }
        catch (Exception ignored) {
            logger.warn("Failed to pause job queue processor.");
        }
    }

这似乎是由 a bug that was resolved in a more recent version of DB2 than I was using 引起的。

Applications are getting large number of timer threads when API timerLevelforQueryTimeout value is not set explicitly in an application using JCC driver version 11.5 GA (JCC 4.26.14) or later. This issue is fixed in 11.5 M4 FP0(JCC 4.27.25).

我在 POM 文件中将版本更新为较新版本 (11.5.6),但这并没有解决问题。原来我的 K8s pod 仍在使用 11.5.0,Maven 表现得很奇怪。然后我应用 (在 POM 文件中使用 dependencyManagement)并加载了较新的版本。