问题事务提交,重试,ConcurrentModificationException

时间:2010-08-24 20:40:41

标签: google-app-engine google-cloud-datastore

当存在异常java.util.ConcurrentModificationException时,我遇到了一些事务问题。

当我遇到这个异常时,我尝试重试但是当我正在查看我的数据存储区查看器时 我的增量不起作用。

例如,当我使用30个并发用户进行测试时,我的数据增加了28倍。 缺少2个递增,我有2个java.util.ConcurrentModificationException。

有人知道为什么吗?我该如何解决这个问题。

int answerNb = Integer.parseInt(req.getParameter("answer"));
PersistenceManager pm = PMF.get().getPersistenceManager();
Query query = pm.newQuery("select from " + Question.class.getName());
query.setFilter("date == dateParam");
query.declareParameters("String dateParam");
List<Question> questions = (List<Question>) query.execute(req.getParameter("date"));

if(!questions.isEmpty()) {
    int retryCount = 0;
    while (retryCount++ < 30) {
      pm.currentTransaction().begin();
      questions.get(0).getAnswers().get(answerNb).increment();

      try {
         pm.currentTransaction().commit();
         break;
      }
      catch (Exception x) {
         //retry
      }
  }

我在java类中的方法增量

public void increment() {
    counter ++;
}

2 个答案:

答案 0 :(得分:0)

使用Vector代替List。当您运行查询并返回列表时,在提交事务时,该列表的修改将保留在数据存储区中。因此,如果您有许多用户尝试一次修改此列表,您将遇到此异常,因为他们都在尝试修改数据存储区中的相同列表。使用Vector,因为它已同步,您的问题就会消失。

答案 1 :(得分:0)

我通过使用密钥和方法pm.getObjectById而不是查询

来解决我的问题
int answerNb = Integer.parseInt(req.getParameter("answer"));            
int retryCount = 0;
Transaction tx;
Question question;

while (retryCount++ < 30) {
  PersistenceManager pm = PMF.get().getPersistenceManager();
  tx = pm.currentTransaction();
  tx.begin();
  question = pm.getObjectById(Question.class,KeyFactory.stringToKey(req.getParameter("key")));          
  question.getAnswers().get(answerNb).increment();
  try {
    tx.commit();
    pm.close();
    break;
  }
  catch (Exception x) {
    pm.close();
    log.info("retry : "+retryCount);
  }
}