2

我需要处理检索待处理记录并将它们更新为“处理中”状态作为工作单元。我想确保下面的代码支持并发和其他线程等到我当前的线程被处理。实现这一目标的最佳方法是什么?

public Collection<Object> processPendingMessages() {
    Collection<Object> messages = null;
    //Retrieve pending messages
    messages = messageDAO.getPendingMessages(Direction.INBOUND);
    //Update pending messages to Inprocess
    if (messages!=null && messages.size()>0) {
        messageDAO.updateMessagesToInprocess(messages); 
    } 
    return messages;
}

非常感谢您的意见。谢谢。

4

3 回答 3

5

您不想通过使用(同步)单独处理 jvm 级别的 DBAccess 并发。在您的情况下,访问数据库是不可能的,仅在 jvm 级别进行同步是不可能的。您还需要在数据库连接级别处理并发,如下所示。就 DBaccess 而言,您还没有提到 DAO 层中的实现类型,但无论它可能是什么,以下 JDBC 隔离级别都应该对您的实现有意义,无论它是什么(JDBC,JPA 与休眠或 EJB 等)。通读下面的隔离级别,并确定哪一个适合您的应用程序。祝您实施一切顺利。

事务隔离级别将事务中的语句作为事务单元指定哪些数据是可见的。这些级别通过定义针对同一目标数据源的事务之间可能的交互,直接影响并发访问的级别。

数据库异常

数据库异常是生成的结果,从单个事务的范围来看似乎不正确,但从所有事务的范围来看是正确的。不同类型的数据库异常描述如下:

脏读发生在: 事务 A 向表中插入一行。事务 B 读取新行。事务 A 回滚。事务 B 可能已根据事务 A 插入的行对系统进行了工作,但该行从未成为数据库的永久部分。

不可重复读取发生在以下情况: 事务 A 读取一行。事务 B 更改行。事务 A 第二次读取同一行并获得新结果。

幻读发生在以下情况: 事务 A 读取 SQL 查询中满足 WHERE 子句的所有行。事务 B 插入满足 WHERE 子句的附加行。事务 A 重新评估 WHERE 条件并获取附加行。

处理上述每个异常的隔离级别

JDBC_TRANSACTION_NONE 这是一个特殊的常量,表示 JDBC 驱动程序不支持事务。

JDBC_TRANSACTION_READ_UNCOMMITTED 此级别允许事务查看对数据的未提交更改。在这个级别上,所有数据库异常都是可能的。

JDBC_TRANSACTION_READ_COMMITTED 在事务内部所做的任何更改在事务提交之前在其外部是不可见的。这可以防止脏读成为可能。

读取的 JDBC_TRANSACTION_REPEATABLE_READ 行保留锁,以便在事务未完成时另一个事务无法更改它们。这不允许脏读和不可重复读。幻读仍然是可能的。

JDBC_TRANSACTION_SERIALIZABLE 表为事务锁定,因此 WHERE 条件不能被其他向表添加值或从表中删除值的事务更改。这可以防止所有类型的数据库异常。

setTransactionIsolation方法可用于更改连接的事务隔离级别。

于 2011-05-07T03:04:49.043 回答
0

你应该让数据库处理并发。

在您的 DAO 中,您可以发出 sql 查询:

// works on oracle.
// query may differ depending on vendor
select * from test where id=? for update 

第一个线程将能够获取锁,但后续线程如果执行查询将阻塞。一旦第一个线程提交/回滚,等待线程中的一个将解除阻塞。这样,您可以让读者一次阅读一个。

于 2011-05-07T07:20:50.720 回答
-1

为了防止代码中的竞争条件,使用synchronized关键字来阻止线程访问代码块,直到前一个线程完成它。

于 2011-05-07T02:20:10.277 回答