【问题标题】:How to avoid ConcurrentModificationExceptions when using EJB3.1 @Asynchronous使用 EJB3.1 @Asynchronous 时如何避免 ConcurrentModificationExceptions
【发布时间】:2010-08-02 16:15:51
【问题描述】:

[我的设置:Java EE 6 应用程序,在 Glassfish 3.0.1 上运行 EJB3.1、CDI/Weld、JSF2]

我阅读了一些关于 EJB3.1 中新的 @Asynchronous 方法的文章,但没有一篇文章提到异步方法的危险以及您真正需要关心的内容。

在我的应用程序中,我有一个@Asynchronous E-Mail 服务,发送大量邮件。我从 CDI/Weld Bean 调用此服务。在我的测试中,我经常遇到 ConcurrentModificationExceptions,但直到现在我才真正理解它有时在哪里以及为什么会崩溃。

只是为了展示我的 Beans 的大致样子,重要的部分:

@Stateful @LocalBean
public class EmailEJB {
  //... Injections

  @Asynchronous
  public Future<Integer> sendEmails(User user, Message message) {
    // ... send mails
    return new AsyncResult<Integer>(1);
  }
}

在我的 CDI-Bean 中,我像这样使用这个 EJB(向 JSF2 公开进度):

@Named @SessionScoped 
public class MessageManager {
  @EJB 
  public EmailEJB emailEJB;

  public FutureEJB<Integer> progress;

  public Integer getProgress() {
    if (progress == null) return 0;
    else {
      return progress.get();
    }
  }

  public String sendMessage() {
    (...)
    progress = emailEJB.sendEmails(user, message);
    (...)
  }
}

我只是想笼统地问一下:我在这里做错了什么吗(范围、注入、使用 Future)?使用 @Asynchronous 方法时我需要注意什么以避免 ConcurrentModificationExceptions?

我将电子邮件作为 EJB 注入。把整个EmailEJB做成异步,用@Inject @Asynchronous注入会不会更好?会有什么不同?

欢迎任何提示!

【问题讨论】:

    标签: asynchronous java-ee-6 cdi ejb-3.1 jboss-weld


    【解决方案1】:

    您对异步方法的使用应该没问题,但我想知道您是否真的希望它是@Stateful。当调用@Asynchronous 方法时,听起来@Stateful bean 中的状态正在另一个线程中被修改(或迭代)。如果@Stateful bean 有一个List 字段并且对该列表的引用被传递到@Stateful bean 之外并被使用,就会发生这种情况。如果调用者线程和异步线程都使用该列表,那将是一件非常糟糕的事情,除非您将其更改为某种并发列表。

    如果您在@Stateful bean 中确实有状态,您最好将其提取到具有最终(不可变)字段的值对象中并将其传递给@Asynchronous @Singleton 方法——可能使用@Lock(READ ) 如果异步方法没有更新 @Singleton 中的任何状态。

    【讨论】:

      【解决方案2】:

      我最大的失败是为我的 CDI bean 使用会话范围。这一次只允许异步 EJB 的一个实例 - 可能会导致 ConcurrentModificationException (我认为它在我重新分配 Future 值的地方)。

      所以@Asynchronous 方法/类似乎是 ConversationScope 的理想候选者。相应地更改了我的 CDI bean,到目前为止没有例外。

      【讨论】:

        猜你喜欢
        • 2016-09-14
        • 2021-01-02
        • 2016-03-24
        • 2012-07-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-25
        • 2014-09-04
        相关资源
        最近更新 更多