使用singelton实现的Ejb缓存

时间:2012-03-24 11:44:52

标签: java java-ee jboss ejb-3.0 ejb-3.1

感谢您就我遇到的问题提出建议。

我正在使用jboss,EJB 3.1环境。

每次用户进入特定屏幕时,它应该是基于保存在数据库上的数据创建树数据类型的触发器。 这个树计算可能需要一些时间,而且性能可能很高。

从UI发送以下请求:

1. refreshTree - a trigger for building the tree
2. isTreeReady - indicating whether the tree is ready to use, and called every x amount of time
3. getTree - return the tree.

在构建时,我应该考虑到多个用户可以尝试同时执行这些操作中的每一个。

我已经考虑将其实现为缓存,如下所示:

@singleton
public class TreeCache{

@EJB
MyTree tree;

boolean isTreeReady = false;

@Lock(LockType.WRITE)
public void refresh(){
      isTreeReady = false;
      tree = calulcateTree() \\ heavy calculation
      isTreeReady = true;
}

public boolean isTreeReady(){
      return isTreeReady;
}

public MyTree getTree(){
      return tree;
}

}

我遇到的问题是可能存在以下情况:

  1. 第一个用户刷新树 - 构建树。
  2. 然后第二个用户开始构建树,并在第一个用户注意到树计算之前将isReady标志初始化为false - 在这种情况下,第一个用户需要等待计算完成(即使他可以使用树)。
  3. 我正在尝试以某种方式使用读锁定(而不是isTreeReady标志),但我无法考虑任何符合我需求的内容。

    你知道我该怎么办?

    感谢。

1 个答案:

答案 0 :(得分:1)

通过使用@Singleton注释,并发性由容器管理。如果一个用户调用一个方法,那么所有方法都有写锁定&其他用户对任何方法的请求必须等待前一个方法返回。

但是您已经在refresh()方法上明确应用了锁,因此其他用户可以同时访问其他方法 - isTreeReady()getTree()等。因此,如果您删除refresh()方法上的锁定,则一次只能有一个用户访问某个方法。

  • LockType.READ:如果可以与许多客户端同时访问或共享该方法,则使用@Lock(LockType.READ)注释单例的业务或超时方法。

  • LockType.WRITE:使用@Lock(LockType.WRITE)注释业务或超时方法,如果 当客户端调用该方法时,单例会话bean应该被锁定到其他客户端。

否则,通过在singleton bean上使用注释@ConcurrencyManagement(ConcurrencyManagementType.BEAN),可以通过使用bean管理器并发获得更好的控制。但是你必须自己明确地管理方法同步和并发。

我无法确定问题的具体情况,但使用正确的锁定策略可能会解决问题。