当前位置: 首页 > 面试题库 >

EJB @Schedule等待方法完成

华知
2023-03-14
问题内容

我想编写一个后台作业(EJB 3.1),该作业每分钟执行一次。为此,我使用以下注释:

@Schedule(minute = "*/1", hour = "*")

工作正常。

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

如果当前执行未完成,是否可以终止调度程序?


问题答案:

如果可能只有一个计时器同时处于活动状态,则有两种解决方案。

首先,@Timer应该在@Singleton。在Singleton中,方法默认情况下是写锁定的,因此,当容器中仍有活动时,尝试调用timer方法时,容器将自动锁定。

以下基本上就足够了:

@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,因为EJB
3.1不允许将读锁升级为写锁)。

计时器bean:

@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");
        }
    }

}

工人豆:

@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:

@Singleton
public class TimerBean {

    @EJB
    private WorkerBean workerBean;

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

}

工人豆:

@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中,然后在其中检查该布尔值,等等。



 类似资料:
  • 我正在编写一个WinForms应用程序,它将数据传输到USB HID类设备。我的应用程序使用了优秀的通用HID库V6.0,可以在这里找到。简单来说,当我需要向设备写入数据时,这是被调用的代码: 当我的代码退出while循环时,我需要从设备中读取一些数据。但是,设备无法立即响应,因此我需要等待此呼叫返回后再继续。由于当前存在,RequestToGetInputReport()声明如下: GetInp

  • 问题内容: 有时我需要等待一种方法完成,主要是在“加载程序”功能上。这是我这样做的方式: 我忍不住觉得这不是等待a 完成的最佳方法。做这个的最好方式是什么? 问题答案: 如果内没有 异步 代码, 则不是异步代码,例如以下代码: 完成后,您将看到警报。 否则(您内部有异步的东西),可以将循环包装在Promise中: 信用:@ rolando-benjamin-vaz-ferreira

  • 我通读了Dart/flatter中的Async/Await/then,试图理解为什么aysnc函数中的Await不会等到完成后再继续。在我的UI中,有一个按钮调用一个异步方法来返回一个位置,该位置总是返回null,并且不等待函数完成。 该函数将调用推送到一个新的UI页面,该页面选择一个位置,并应返回一个结果。如何使该函数等待结果?我不是在使用异步吗?

  • 在搜索了很多类似问题的答案后,我仍然没有找到适合我需要的解决方案。 基本上,我有一个while循环,我想等待repaint()方法完成,然后再开始该循环的另一次迭代。 更详细地说,我有一些片段是在扩展JComponent的MapPanel类的paintComponent方法中绘制的。然后,当用户单击按钮时,算法开始搜索从“上部”线段开始的交点(使用endpoint作为事件点)。这个算法基本上就是我

  • 问题内容: 我是J2EE6中@Schedule注释的新手 我想使用EJB 3.x和Glassfish 3.1来运行作业。 javax.ejb.Schedule对我们来说似乎是一个不错的选择,因此我们可以将自定义时间视为: 在这里,我们希望从数据库中获取参数,因此每个月都会对其进行更改。有什么干净的解决方案吗? 问题答案: 不可以,没有解决方案,因为注释属性通常应该是编译时间常数。 当需要更大的灵活

  • 问题内容: 我有一个登录框架,我必须从另一个线程等待。成功登录后,框架将自行处置。我想弹出该应用程序的主框架。现在,我正在观看一个布尔值,以确定何时启动主机。正确的做法是什么?观看布尔值只是感觉并不优雅。 问题答案: 如果您有Java 5或更高版本,则可以使用CountDownLatch。例如,假设主框架最初处于控制状态,则让主框架创建一个倒数为1的,然后将此锁存器传递给登录框架。然后让主机等待锁