gpt4 book ai didi

java - 当我使用 Executors.newSingleThreadScheduledExecutor 创建 ScheduledExecutorService 时,它​​运行许多线程

转载 作者:太空宇宙 更新时间:2023-11-04 12:30:28 34 4
gpt4 key购买 nike

上下文:

  • 这是一个 Jersey 应用程序
  • Tomcat 服务器上运行
  • 使用 Hibernate 连接到 MySQL 数据库
  • 一切都在 Netbeans

我正在创建一个 ScheduledExecutorService 来每天在特定时间运行。但是,当它运行时,它会创建许多与数据库的连接。我想这是因为当我重新运行应用程序时线程没有被销毁,所以许多 ScheduledExecutorService 在 JVM 中构建并且全部同时执行。但是,我不确定原因是什么。

我使用仅创建守护线程的 ThreadFactory 创建 ScheduledExecutorService,因此当我重新运行应用程序时,我认为所有守护线程都应该被销毁,以便只有一个 ScheduledExecutorService 存在。

这里是 ScheduledExecutorService 的创建:

ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = Executors.defaultThreadFactory().newThread(r);
t.setDaemon(true);
return t;
}
});

以下是它每天在特定时间运行的方式:

public void startExecutionAt(int targetHour, int targetMin, int targetSec){
long delay = computeNextDelay(targetHour, targetMin, targetSec);

mExecutorService.schedule(new Runnable() {
@Override
public void run() {
Thread t = new Thread(new CustomRunnable());
t.setDaemon(false);
t.start();
startExecutionAt(targetHour, targetMin, targetSec);
}
}, delay, TimeUnit.SECONDS);
}

我知道它正在创建许多与 MySQL 的连接,因为在 P6Spy 日志中,当 CustomRunnable 只运行一个从表中选择 5 条记录的 Hibernate 查询时,执行 CustomRunnable 时会产生许多连接和查询。

对于可能发生的事情有什么想法吗?

最佳答案

你显然滥用了你的ScheduledExecutorService,这是你应该做的:

public void startExecutionAt(int targetHour, int targetMin, int targetSec){
long delay = computeNextDelay(targetHour, targetMin, targetSec);

mExecutorService.scheduleAtFixedRate(
new CustomRunnable(),
1000L * delay,
TimeUnit.DAYS.toMillis(1),
TimeUnit.MILLISECONDS
);
}

您一次调用此方法,它将以 delay 作为初始延迟启动您的任务,然后每天在同一确切时间启动您的任务。

更多详情here .

事实上,您当前在执行任务时随时创建一个新线程,然后再次调用该方法来安排下一次执行,这不是您应该做的,该任务已经在池中执行,无需创建新的线程,而且当您可以直接使用ScheduledExecutorService时,无需再次手动安排。

响应更新:

由于您的情况安排似乎更复杂,因此您应该这样做:

public void startExecutionAt(int targetHour, int targetMin, int targetSec){
long delay = computeNextDelay(targetHour, targetMin, targetSec);

mExecutorService.schedule(new Runnable() {
@Override
public void run() {
try {
new CustomRunnable().run();
} finally {
startExecutionAt(targetHour, targetMin, targetSec);
}
}
}, delay, TimeUnit.SECONDS);
}

这样您就不会无缘无故地创建和启动新线程。

问题的第二部分应该通过分别在初始化和销毁​​的 ServletContext 上正确启动和关闭 ScheduledExecutorService 来解决,换句话说,管理调度程序的类应该是 ServletContextListener

public class MyServletContextListener implements ServletContextListener {
private ScheduledExecutorService executorService;
public void contextInitialized(ServletContextEvent sce) {
executorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = Executors.defaultThreadFactory().newThread(r);
t.setDaemon(true);
return t;
}
});
}

public void contextDestroyed(ServletContextEvent sce) {
executorService.shutdownNow();
}

public void startExecutionAt(int targetHour, int targetMin, int targetSec){
// code defined above here
}
}

如果您需要服务来使其工作,请使用 CDI 通过注入(inject)来获取它们。

关于java - 当我使用 Executors.newSingleThreadScheduledExecutor 创建 ScheduledExecutorService 时,它​​运行许多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37898117/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com