ScheduledExecutorService在我使用Executors.newSingleThreadScheduledExecutor

时间:2016-06-18 14:34:49

标签: java multithreading hibernate

上下文:

  • 这是Jersey申请
  • Tomcat服务器上运行
  • 使用MySQL
  • 连接到Hibernate数据库
  • 全部Netbeans

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

我使用ThreadFactory创建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日志中,CustomRunnable执行Hibernate时会有很多连接和查询只运行一个.header { margin: 0; padding: 0px; color: white; } .my-header{ background-color: #003399; height: 25px; } .header li, form { display: inline; } .header li { line-height: 25px; } .header-normal li a{ text-decoration: none; color: white; line-height: 25px; padding-right: 10px; vertical-align: middle; padding-left: 5px; font-size: 14pt; font-family: "Palatino Linotype", "Book Antiqua", Palatino, serif; } .normal li a:hover{ color: #ff6699; } .AlignLeft { text-align: left; float: left; } .AlignRight { text-align: right; float:right; }查询,从表中选择5条记录。

关于可能发生什么的任何想法?

1 个答案:

答案 0 :(得分:0)

你显然滥用了你的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

事实上,您当前在任务执行时创建了一个新线程,然后再次调用该方法来安排下一次执行,这不是您应该做的,该任务已在池中执行,无需创建新任务Thread此外,当您可以使用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);
}

通过这种方式,您无法创建和创建新线程。

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

ServletContextListener

如果您需要服务来使其发挥作用,请使用CDI通过注射来获取它们。