Java EE并发&锁定 [英] Java EE concurrency & locking

查看:255
本文介绍了Java EE并发&锁定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a MDB (Message driven bean) that receives messages with String which represent a word. Also I have a table in the database. The MDB should store in the table, the words and the number of times each word was received (counter).

问题是为了获得更好的性能MDB开始许多实例,并且当不同的实例接收到相同的新单词时,它们都创建了计数为1的相同行。

The problem is that to get better performance the MDB started in many instances and when the same new word is received by different instances they both create the same row with count of 1.

为了解决这个问题,我应该使字段唯一,那么第二个实例将在提交时失败,重新传输消息,这将工作,但可能有问题。这是一个很好的做法吗?

To solve this I should make the word field unique and then the second instance will fail on commit, retransmitting the message, which will work, but may be problematic. Is it a good practice ?

另一个解决方案是合并这些行后加总计数器。但是如果另一个实例将在更新中间增加计数器。

Another solution is to merge these lines afterwards summing the counter. But what if another instance will increase the counter in the middle of the update.

如果两个实例尝试增加计数器会怎么样? @Version 应该够了吗?

What if two instances try to increase the counter ? @Version should be enough?

我不知道这里是什么是正确的解决方案。

I'm not sure what is the proper solution here. How would you handle such cases ?

您还可以建议一些关于并发性做法的书籍(不是使用 synchronized 因为我需要支持Java EE,并且可能运行一组应用程序服务器)

Also can you suggest some books about concurrency practices (not about the use of synchronized as I need to support Java EE and may run a cluster of application servers)?

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

Update: After reading more about EJB and JPA I suppose I want something like an locking entity. For example I can create a new table with only id and key columns and data like this:

ID | KEY
1  | WORDS_CREATE_LOCK

这样当我需要处理一个新单词时,我会做这样的事情,不确定它会编译):

So that when I need to handle a new word I will do something like this (not exact code, not sure it will even compile):

// 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。

If it helps I'm using JBoss 4.2.

我有一个新的想法。我可以创建两个MDB:

I have a new idea for this. I can create two MDBs:

第一个MDB允许许多实例,它将处理所有的消息,如果没有找到字将发送字到第二个MDB

1st MDB with many instances allowed, that will handle all the messages and if the word is not found will send the word to the second MDB

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

2nd MDB with only one instance allowed, will handle the messages serially and will allow creation of new word

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

The best part: no entire table/method/process locking, only row locking on counter update

这有多好?

感谢。

推荐答案

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

If you are looking for performance, no locking, etc. I would suggest to have another table: (word, timestamp). Your MDBs will just insert the word and the timestamp. Another process will count and update the table with the totals.

这篇关于Java EE并发&amp;锁定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆