首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >EJB @Schedule等待方法完成

EJB @Schedule等待方法完成
EN

Stack Overflow用户
提问于 2013-01-18 23:26:59
回答 4查看 47.2K关注 0票数 36

我想写一个后台作业(EJB3.1),它每分钟执行一次。为此,我使用以下注释:

代码语言:javascript
复制
@Schedule(minute = "*/1", hour = "*")

运行得很好。

但是,有时这项工作可能需要一分钟以上的时间。在这种情况下,计时器仍然被触发,从而导致线程问题。

如果当前的执行没有完成,有没有可能终止调度器?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-01-19 20:44:51

如果同时只有一个定时器处于活动状态,那么有几种解决方案。

首先,@Timer可能应该出现在@Singleton上。在Singleton中,方法在默认情况下是写锁定的,所以当尝试调用timer方法时,容器将自动锁定,而其中仍有活动。

以下内容基本上就足够了:

代码语言:javascript
复制
@Singleton
public class TimerBean {

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

        System.out.println("Called");
        Thread.sleep(10000);
    }
}

默认情况下,atSchedule是写锁定的,并且其中只能有一个活动线程,包括由容器发起的调用。

一旦被锁定,容器可能会重试计时器,因此为了防止这种情况,您可以使用读锁,并委托给第二个bean (第二个bean是必需的,因为EJB3.1不允许将读锁升级为写锁)。

计时器bean:

代码语言:javascript
复制
@Singleton
public class TimerBean {

    @EJB
    private WorkerBean workerBean;

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

        try {
            workerBean.doTimerWork();
        } catch (Exception e) {
            System.out.println("Timer still busy");
        }
    }

}

工作bean:

代码语言:javascript
复制
@Singleton
public class WorkerBean {

    @AccessTimeout(0)
    public void doTimerWork() throws InterruptedException {
        System.out.println("Timer work started");
        Thread.sleep(12000);
        System.out.println("Timer work done");
    }
}

这可能仍然会在日志中打印一个嘈杂的异常,所以一个更详细但更安静的解决方案是使用显式布尔值:

计时器bean:

代码语言:javascript
复制
@Singleton
public class TimerBean {

    @EJB
    private WorkerBean workerBean;

    @Lock(READ)
    @Schedule(second = "*/5", minute = "*", hour = "*", persistent = false)
    public void atSchedule() {
        workerBean.doTimerWork();
    }

}

工作bean:

代码语言:javascript
复制
@Singleton
public class WorkerBean {

    private AtomicBoolean busy = new AtomicBoolean(false);

    @Lock(READ)
    public void doTimerWork() throws InterruptedException {

        if (!busy.compareAndSet(false, true)) {
            return;
        }

        try {
            System.out.println("Timer work started");
            Thread.sleep(12000);
            System.out.println("Timer work done");
        } finally {
            busy.set(false);
        }
    }

}

还有一些可能的变化,例如,你可以将繁忙检查委托给一个拦截器,或者将一个只包含布尔值的单例注入到计时器bean中,然后检查那里的布尔值,等等。

票数 68
EN

Stack Overflow用户

发布于 2013-12-06 23:26:35

我遇到了同样的问题,但解决方法略有不同。

代码语言:javascript
复制
@Singleton
public class DoStuffTask {

    @Resource
    private TimerService timerSvc;

    @Timeout
    public void doStuff(Timer t) {
        try {
            doActualStuff(t);
        } catch (Exception e) {
            LOG.warn("Error running task", e);
        }
        scheduleStuff();
    }

    private void doActualStuff(Timer t) {

        LOG.info("Doing Stuff " + t.getInfo());
    }

    @PostConstruct
    public void initialise() {
        scheduleStuff();
    }

    private void scheduleStuff() {
        timerSvc.createSingleActionTimer(1000l, new TimerConfig());
    }

    public void stop() {
        for(Timer timer : timerSvc.getTimers()) {
            timer.cancel();
        }
    }

}

这是通过设置一个在将来执行的任务(在本例中是在一秒内执行)来实现的。在任务结束时,它会再次调度任务。

编辑:更新以将“内容”重构到另一个方法中,这样我们就可以保护异常,从而使计时器的重新调度始终发生。

票数 7
EN

Stack Overflow用户

发布于 2016-10-07 18:09:45

从JavaEE7开始,就可以使用“支持EE的”ManagedScheduledExecutorService,即在WildFly中:

例如,在一个服务中,注入standalone.xml中配置的缺省“managed-scheduled-executor- @Singleton @Startup @LocalBean

代码语言:javascript
复制
@Resource
private ManagedScheduledExecutorService scheduledExecutorService;

@PostConstruct中调度要执行的任务,即使用固定延迟每秒执行一次

代码语言:javascript
复制
scheduledExecutorService.scheduleWithFixedDelay(this::someMethod, 1, 1, TimeUnit.SECONDS);

scheduleWithFixedDelay

创建并执行一个周期性操作,该操作首先在给定的初始延迟之后启用,随后在一个执行的终止和下一个执行的开始之间具有给定的延迟。

请勿关闭@PreDestroy中的调度程序

托管的调度执行器服务实例由应用程序服务器管理,因此禁止Java应用程序调用任何与生命周期相关的方法。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14402068

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档