消息驱动Bean中的并发性-线程安全的Java EE5与EE6 [英] Concurrency in Message Driven Bean - Thread safe Java EE5 vs. EE6

查看:161
本文介绍了消息驱动Bean中的并发性-线程安全的Java EE5与EE6的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到的情况是,我需要将一组操作封装到一个事务中,并且必须对MDB保持线程安全.

I have a situation where I need a set of operations be enclosed into a single transaction and be thread safe from a MDB.

如果线程A执行指令1,则不希望其他线程能够读取(至少不相同)线程A正在处理的数据. 在下面的代码中,由于IMAGE表包含来自不同来源的重复数据,因此将导致重复的INFRANCTION.需要避免的情况.

If thread A executes the instruction 1, do not want other threads can read, at least not the same, data that thread A is processing. In the code below since IMAGE table contains duplicated data, coming from different sources, this will lead in a duplicated INFRANCTION. Situation that needs to be avoided.

我发现的实际解决方案是为每条新消息声明一个新事务并同步整个事务. 简化代码:

The actual solution that I found is declaring a new transaction for each new message and synchronize the entire transaction. Simplifying the code:

@Stateless
InfranctionBean{
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    checkInfranction(String plate){
        1. imageBean.getImage(plate); // read from table IMAGE
        2. infranctionBean.insertInfranction(String plate); // insert into table INFRANCTION
        3. imageBean.deleteImage(String plate); //delete from table IMAGE
    }
}

@MessageDriven
public class ImageReceiver {

    private static Object lock = new Object();

    public void onMessage(Message msg){
        String plate = msg.plate;

        synchronized (lock) {
            infanctionBean.checkInfranction(plate);
        }
    }
}

我知道EJB规范不建议在EJB内部使用同步块.如果applicaton服务器在两个节点群集中运行,这甚至可能导致问题.

I am aware that using synchronized blocks inside the EJB is not recommanded by EJB specification. This can lead even in problems if the applicaton server runs in two node cluster.

似乎EE6引入了针对该场景的解决方案,即EJB Singleton. 在这种情况下,我的解决方案将是这样的:

Seems like EE6 has introduced a solution for this scenario, which is the EJB Singleton. In this case, my solution would be something like this:

@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
@Singleton
InfranctionBean{

    @Lock(LockType.WRITE)
    checkInfranction(String plate){
        1...
        2...
        3...
    }
}

从MDB不需要使用同步块,因为容器将处理并发性. 使用@Lock(WRITE),容器可确保对checkInfranction()中的单线程进行访问.

And from MDB would not be neccessary the usage of synchronized block since the container will handle the concurrency. With @Lock(WRITE) the container guarantees the access of single thread inside checkInfranction().

我的问题是:如何在EE5中处理这种情况?有没有使用同步块的更干净的解决方案?

My queston is: How can I handle this situation in EE5? There is a cleaner solution without using synchronized block?

环境:Java5,jboss-4.2.3.GA,Oracle10.

Environment: Java5,jboss-4.2.3.GA,Oracle10.

实际解决方案

@Stateless
InfranctionBean{
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    checkInfranction(String plate){    
        1. imageBean.lockImageTable(); // lock table IMAGE in exclusive mode
        2. imageBean.getImage(plate); // read from table IMAGE
        3. infranctionBean.insertInfranction(String plate); // insert into table INFRANCTION
        4. imageBean.deleteImage(String plate); //delete from table IMAGE
    }
}

@MessageDriven
public class ImageReceiver {
    public void onMessage(Message msg){
        infanctionBean.checkInfranction(msg.plate);
    }
}

在20.000条传入消息(同时发送一半)上,该应用程序正常运行.

On 20.000 incoming messages (half of them simultaneously) seems the application works ok.

推荐答案

@Lock(WRITE)只是单个应用程序/JVM中的锁,因此,除非您可以保证只有一个应用程序/JVM在访问数据,否则您将反正得不到太多保护.如果您仅在寻找单个应用程序/JVM保护,则EE 5中最好的解决方案是ReadWriteLock或同步块. (EJB规范具有阻止应用程序执行此操作的语言,以避免损害服务器的线程管理,因此请注意不要无限期地阻塞,不要忽略中断等.)

@Lock(WRITE) is only a lock within a single application/JVM, so unless you can guarantee that only one application/JVM is accessing the data, you're not getting much protection anyway. If you're only looking for single application/JVM protection, the best solution in EE 5 would be a ReadWriteLock or perhaps a synchronized block. (The EJB specification has language to dissuade applications from doing this to avoid compromising the thread management of the server, so take care that you don't block indefinitely, that you don't ignore interrupts, etc.)

如果您正在寻找更健壮的跨应用程序/JVM解决方案,我将使用数据库锁或隔离级别,而不是尝试依赖JVM同步原语.无论使用哪种EJB版本,这都是最好的解决方案.

If you're looking for a more robust cross-application/JVM solution, I would use database locks or isolation levels rather than trying to rely on JVM synchronized primitives. That is probably the best solution regardless of the EJB version being used.

这篇关于消息驱动Bean中的并发性-线程安全的Java EE5与EE6的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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