如何延迟 ManagedScheduledExecutorService 直到容器未暂停?

How to delay ManagedScheduledExecutorService until container is not suspended?

我正在调查 javax.enterprise.concurrent.ManagedScheduledExecutorServiceWildFly Full 11.0.0.Final (WildFly Core 3.0.8.Final) 上的使用情况。

我的启动 EJB 类似于

import java.time.LocalTime;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.enterprise.concurrent.ManagedScheduledExecutorService;

@Startup
@Singleton
public class Scheduler {

    static final long INITIAL_DELAY = 0L;
    static final long PERIOD = 2L;

    @Resource
    ManagedScheduledExecutorService scheduler;

    @PostConstruct
    public void init() {
        this.scheduler.scheduleAtFixedRate(this::invokePeriodically, INITIAL_DELAY, PERIOD, TimeUnit.SECONDS);
    }

    public void invokePeriodically() {
        System.out.println("@@@@@@@@@@ - Don't use sout in prod " + LocalTime.now());
    }

}

在服务器启动时我看到这些消息:-

10:15:26,022 ERROR [org.jboss.as.ee] (EE-ManagedScheduledExecutorService-default-Thread-1) WFLYEE0110: 
Failed to run scheduled task: java.lang.IllegalStateException: 
WFLYEE0111: Cannot run scheduled task com.research.Scheduler$$Lambda2/1222053658@1b50d7a0 as container is suspended
    at org.jboss.as.ee.concurrent.ControlPointUtils$ControlledScheduledRunnable.run(ControlPointUtils.java:164)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
    at org.glassfish.enterprise.concurrent.internal.ManagedScheduledThreadPoolExecutor$ManagedScheduledFutureTask.access1(ManagedScheduledThreadPoolExecutor.java:383)
    at org.glassfish.enterprise.concurrent.internal.ManagedScheduledThreadPoolExecutor$ManagedScheduledFutureTask.run(ManagedScheduledThreadPoolExecutor.java:534)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
    at org.glassfish.enterprise.concurrent.ManagedThreadFactoryImpl$ManagedThread.run(ManagedThreadFactoryImpl.java:250)
    at org.jboss.as.ee.concurrent.service.ElytronManagedThreadFactory$ElytronManagedThread.run(ElytronManagedThreadFactory.java:78)

当我增加初始延迟时

static final long INITIAL_DELAY = 60L;

服务器启动是"clean"。

是否有可用的 mechanisms/techniques 我可以使用(除了猜测我的初始延迟应该多长时间)来始终获得干净的服务器启动并尽快安排我的 EJB?

您最好为此目的使用 EJB 计时器。在 EJB 投入使用之前,服务器保证不会触发计时器方法。

您可以在 javax.ejb.TimerService 验证 API 用于创建计时器。

请注意,如果您创建持久性计时器,那么当您重新启动服务器时,服务器将尝试 "catch up" 错过触发。

如果它只是一个周期性任务,那么不要创建持久性计时器。

回答这个问题有点晚了,但您可以在方法声明上方使用内置的 EE 注释:@Schedule,而不是依赖另一个 API。它提供了在内部确定超时和持久性的能力。