Java EE 并发和锁定

标签 java jakarta-ee concurrency locking

我有一个 MDB(消息驱动的 bean),它接收带有表示单词的字符串的消息。我在数据库中也有一个表。 MDB应该在表中存储单词和每个单词被接收的次数(计数器)。

问题在于,为了获得更好的性能,MDB 在许多实例中启动,并且当不同实例接收到相同的新词时,它们都会创建计数为 1 的相同行。

要解决这个问题,我应该使 word 字段唯一,然后第二个实例将在提交时失败,重新传输消息,这会起作用,但可能会有问题。这是一个好的做法吗?

另一种解决方案是在对计数器求和后合并这些行。但是,如果另一个实例将在更新过程中增加计数器怎么办。

如果两个实例试图增加计数器怎么办? @Version 应该够了吧?

我不确定这里的正确解决方案是什么。您将如何处理此类情况?

您还可以推荐一些关于并发实践的书籍吗(不是关于 synchronized 的使用,因为我需要支持 Java EE 并且可能运行一个应用程序服务器集群)?


更新: 在阅读了有关 EJB 和 JPA 的更多信息后,我想我想要类似锁定实体的东西。例如,我可以创建一个只有 id 和 key 列以及数据的新表,如下所示:

ID | KEY
1  | WORDS_CREATE_LOCK

所以当我需要处理一个新词时,我会做这样的事情(不是确切的代码,不确定它是否会编译):

// MAIN FUNCTION
public void handleWord(String wordStr) {
  Word w = getWord(wordStr);

  if (w == null)
    w = getNewOrSychronizedWord(wordStr);

  em.lock(w);
  w.setCounter(w.getCounter() + 1);
  em.unlock(w);
}

// Returns Word instance or null if not found
private Word getWord(String wordStr) {
  Word w = null;

  Query query = em.createQuery("select w from words as w where w.string = :wordStr order by w.id asc");
  query.setParameter("wordStr", wordStr);
  List<Word> words = query.getResultList();

  if (words.getSize() > 0)
    w = words.get(0);

  return w;
}

// Handles locking to prevent duplicate word creation
private Word getNewOrSynchronizedWord(String wordStr) {
  Word w = null;
  Locks l = em.find(WORDS_CREATE_LOCK_ID, Locks.class);
  em.lock(l);

  Word w = getWord(wordStr);

  if (w == null) {
    w = new Word(wordStr);
    em.persist(w);
  }

  em.unlock(l);
  return w;
}

所以问题是它会那样工作吗?我可以在不维护带锁定行的数据库表的情况下做同样的事情吗?可能是某种 Java EE 容器锁定机制?

如果有帮助,我正在使用 JBoss 4.2。


我对此有了新的想法。我可以创建两个 MDB:

第一个 MDB 允许许多实例,它将处理所有消息,如果未找到该词,则将该词发送到第二个 MDB

第二个 MDB 只允许一个实例,将连续处理消息并允许创建新词

最好的部分:没有整个表/方法/进程锁定,只有计数器更新时的行锁定

这有多好?

谢谢。

最佳答案

如果您正在寻找性能、无锁定等。我建议有另一个表:(word, timestamp)。您的 MDB 将只插入单词和时间戳。另一个进程将计数并用总数更新表格。

关于Java EE 并发和锁定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/834843/

相关文章:

java - Dockererized Kong 在 Windows 上给出 "An invalid response was received from the upstream server"

go - 使用 channel 同步多个 goroutine

java - 使用 help-mojo 阶段和 maven-plugin-plugin 编译 Maven 插件

java - server.port 和 server.context-path 在部署到 tomcat 时不生效

java - weblogic 是开源的吗?

jakarta-ee - EJB 3.1 |通过 JNDI 调用远程 session bean 时出错

rest - 在 jersey 1.8 和 tomcat 7 Resful 和 eclipse 中找不到 404

java - 并发矩阵乘法。适配器模式的使用

java - Futures 如何在底层提高并发性?

java - 图形布局和运行时的奇怪问题