JEE 7 Scheduler 如何在不阻塞调度程序的情况下分叉任务

JEE 7 Scheduler how to fork a task without blocking the scheduler

在 JEE 7 WildFly 环境中,我想执行一个任务(worker 的一种方法class)而不阻塞调度程序。 这样调度程序就可以启动多个 "tasks/threads",它们 运行 独立于调度程序(即发即弃)。

在普通的旧 Java 中,我只需要启动一个新线程,但在托管容器中,这是被禁止的。

我怎样才能达到这个目标?

这是一个简短的原始示例(不起作用)以阐明我想要做什么:

@Startup
@Singleton
public class MyScheduler {

    public static final Logger LOGGER = LogManager.getLogger(MyScheduler.class);

    private int counter = 0;

    @Schedule(second = "*/5", minute = "*", hour = "*", persistent = false)
    public void atSchedule() throws InterruptedException {

        LOGGER.info("{}. scheduler call - every five secs.", (++counter));

        final Worker worker = new Worker(counter);
        worker.doSomethingWithoutBlocking();

        LOGGER.info("Scheduler done.");

    }   

} // class MyScheduler 


@Stateless
@Asynchronous
public class Worker {

    public static final Logger LOGGER = LogManager.getLogger(Worker.class);

    private int nr; 

    public Worker() {}

    public Worker(final int nr) {
        this.nr = nr;
    }

    @Asynchronous
    public void doSomethingWithoutBlocking() {

        for(long i = 0; i < 10000000000L; i++) {

            if(i % 1000000000 == 0) {
                LOGGER.info("{}. Worker: i = {}", nr, i);
            } // if

        } // for

    }


} // class Worker

不要认为这是最好的主意,但是:

@Startup
@Singleton
public class MyScheduler {

   public static final Logger LOGGER = LogManager.getLogger(MyScheduler.class);

private int counter = 0;


@Schedule(second = "*/5", minute = "*", hour = "*", persistent = false)
public void atSchedule() throws InterruptedException {

    LOGGER.info("{}. scheduler call - every five secs.", (++counter));
    final Worker worker = new Worker(counter);
    runWithoutBlocking(worker);
    LOGGER.info("Scheduler done.");
}

@Async
void runWithoutBlocking(Worker worker) {
    worker.doSomethingWithoutBlocking();
}   

}

建议您使用应用服务器提供的ManagedExecutorService。鉴于您不需要 Worker class 成为 EJB,下面给出的代码应该可以解决问题。我还没有在 Wildfly 上尝试 运行,但在 Payara Server 上进行了验证。

@Singleton
public class Scheduler {
    private int counter = 0;
    private static final Logger LOGGER = Logger.getLogger(Scheduler.class.getName());

    @Resource
    ManagedExecutorService mes;

    @Schedule(second = "*/5", minute = "*", hour = "*", persistent = false)
    public void atSchedule() throws InterruptedException {
        LOGGER.info(String.format("%d. scheduler call - every five secs.", (++counter)));
        mes.submit(() -> {
            final Worker worker = new Worker(counter);
            worker.doSomething();
        });

        LOGGER.info("Scheduler done.");

    }   
}

public class Worker {
    private static final Logger LOGGER = Logger.getLogger(Worker.class.getName());
    private int nr; 

    public Worker() {}

    public Worker(final int nr) {
        this.nr = nr;
    }

    public void doSomething() {
        for(long i = 0; i < 10000000000L; i++) {
            if(i % 1000000000 == 0) {
                LOGGER.info(String.format("%d. Worker: i = %d", nr, i));
            } // if
        } // for
    }
}