ejb 3.1 中的计时器服务 - 调度调用超时问题

发布于 2024-08-29 20:25:13 字数 1371 浏览 1 评论 0原文

我使用 @Singleton、@Schedule 和 @Timeout 注释创建了简单的示例,以尝试它们是否能解决我的问题。

场景是这样的:EJB 每 5 秒调用一次“检查”函数,如果满足某些条件,它将创建单个操作计时器,该计时器将以异步方式调用一些长时间运行的进程。 (这是一种队列实现类型的东西)。然后它会继续检查,但是当长时间运行的进程存在时,它不会启动另一个进程。

下面是我想出的代码,但这个解决方案不起作用,因为它看起来像我正在进行的异步调用实际上阻止了我的 @Schedule 方法。

@Singleton
@Startup
public class GenerationQueue {

    private Logger logger = Logger.getLogger(GenerationQueue.class.getName());

    private List<String> queue = new ArrayList<String>();

    private boolean available = true;

    @Resource
    TimerService timerService;

    @Schedule(persistent=true, minute="*", second="*/5", hour="*")
    public void checkQueueState() {

        logger.log(Level.INFO,"Queue state check: "+available+" size: "+queue.size()+", "+new Date());

        if (available) {

            timerService.createSingleActionTimer(new Date(), new TimerConfig(null, false));
        }

    }

    @Timeout
    private void generateReport(Timer timer) {

        logger.info("!!--timeout invoked here "+new Date());

        available = false;

        try {

            Thread.sleep(1000*60*2); // something that lasts for a bit

        } catch (Exception e) {}

        available = true;

        logger.info("New report generation complete");

    }

我在这里缺少什么或者我应该尝试不同的方法?欢迎任何想法:)

使用 Glassfish 3.0.1 最新版本进行测试 - 忘了提及

I have created simple example with @Singleton, @Schedule and @Timeout annotations to try if they would solve my problem.

The scenario is this: EJB calls 'check' function every 5 secconds, and if certain conditions are met it will create single action timer that would invoke some long running process in asynchronous fashion. (it's sort of queue implementation type of thing). It then continues to check, but while the long running process is there it won't start another one.

Below is the code I came up with, but this solution does not work, because it looks like asynchronous call I'm making is in fact blocking my @Schedule method.

@Singleton
@Startup
public class GenerationQueue {

    private Logger logger = Logger.getLogger(GenerationQueue.class.getName());

    private List<String> queue = new ArrayList<String>();

    private boolean available = true;

    @Resource
    TimerService timerService;

    @Schedule(persistent=true, minute="*", second="*/5", hour="*")
    public void checkQueueState() {

        logger.log(Level.INFO,"Queue state check: "+available+" size: "+queue.size()+", "+new Date());

        if (available) {

            timerService.createSingleActionTimer(new Date(), new TimerConfig(null, false));
        }

    }

    @Timeout
    private void generateReport(Timer timer) {

        logger.info("!!--timeout invoked here "+new Date());

        available = false;

        try {

            Thread.sleep(1000*60*2); // something that lasts for a bit

        } catch (Exception e) {}

        available = true;

        logger.info("New report generation complete");

    }

What am I missing here or should I try different aproach? Any ideas most welcome :)

Testing with Glassfish 3.0.1 latest build - forgot to mention

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

过气美图社 2024-09-05 20:25:13

单例的默认@ConcurrencyManagement是ConcurrencyManagementType.CONTAINER,默认@Lock是LockType.WRITE。基本上,这意味着每个方法(包括generateReports)都被有效地标记为synchronized 关键字,这意味着checkQueueState 将在generateReport 运行时阻塞。

考虑使用 ConcurrencyManagement(ConcurrencyManagementType.BEAN) 或 @Lock(LockType.READ)。如果这两个建议都没有帮助,我怀疑您已经发现了 Glassfish 错误。

顺便说一句,您可能需要 permanent=false,因为您可能不需要保证 checkQueueState 方法每 5 秒触发一次,即使您的服务器处于离线状态也是如此。换句话说,当您将服务器恢复在线时,您可能不需要容器来触发“追赶”。

The default @ConcurrencyManagement for singletons is ConcurrencyManagementType.CONTAINER with default @Lock of LockType.WRITE. Basically, that means every method (including generateReports) is effectively marked with the synchronized keyword, which means that checkQueueState will block while generateReport is running.

Consider using ConcurrencyManagement(ConcurrencyManagementType.BEAN) or @Lock(LockType.READ). If neither suggestion helps, I suspect you've found a Glassfish bug.

As an aside, you probably want persistent=false since you probably don't need to guarantee that the checkQueueState method fires every 5 seconds even when your server is offline. In other words, you probably don't need the container to fire "catch ups" when you bring your server back online.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文