【发布时间】:2021-10-03 04:27:38
【问题描述】:
我有一些使用 Spring Batch 的 Java 应用程序。我有一个用作队列的表,其中包含有关客户端请求的作业的信息(当客户端请求要执行的任务时,会在此队列中添加一行)。
在我的一个课程中,会运行一个 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.");
}
}
【问题讨论】:
-
创建定时器的代码在哪里?
-
我没有创建任何东西,所以我很惊讶。不知道如何正确地进行分析。
-
你尝试过什么调试?你在 Timer 的构造函数中下过断点吗?
-
没有看到这段代码是如何启动的或者调用了什么代码,这是无法回答的。
-
我只是在 Timer 构造函数中放置了一个断点,并看到线程是从
dequeueJobEntry()中创建的。似乎在建立连接时会发生这种情况。这很有趣,因为在某些时候,容器中也发生了错误,其中存在连接问题、连接过多或类似问题。我会将相关代码添加到我的答案中。
标签: java spring kubernetes threadpool