简体   繁体   中英

Ejb cache with singelton implementation

I would appreciate your advice about an issue I have.

I'm working with jboss, EJB 3.1 environment.

each time the user entering a specific screen, it should be a trigger for creating a tree data type which based on a data that saved on the database. this tree calculation can take some time, and it's can be heavy on performance.

the following requests are sent from 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.

when building this I should take into consideration that multiple users can try to perform each one of those actions simultaneously.

I've thought about implementing it as a cache as follow :

@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;
}

}

the issue I have with that is that there can be a scenario in which :

  1. first user refreshing the tree - and the tree is built.
  2. then second user start to build the tree, and initialize the isReady flag to false, before the first user has noticed about the tree calculation - in this case the first user will need to wait to the calculation to be completed (even though he could have use the tree).

I'm trying to think a bout using a read lock in some way (instead of the isTreeReady flag), but I can't think about any that will fit my needs.

do you have an idea what can I do?

thanks.

By using @Singleton annotation, the concurrency is managed by the container. If one user invokes a method, then all methods have write lock & requests from other users for any method must have to wait for the previous one to return.

But you have applied lock explicitly on refresh() method, so other methods - isTreeReady() , getTree() etc. can be accessed concurrently by other users. Therefore if you remove lock on refresh() method, then only one user will be able to access a method at a time.

  • LockType.READ : Annotate a singleton's business or timeout method with @Lock(LockType.READ) if the method can be concurrently accessed, or shared, with many clients.

  • LockType.WRITE : Annotate the business or timeout method with @Lock(LockType.WRITE) if the singleton session bean should be locked to other clients while a client is calling that method.

Else, you can gain better control by using bean manager concurrency by using annotation @ConcurrencyManagement(ConcurrencyManagementType.BEAN) on singleton bean. But you have to manage method synchronization, concurrency explicitly on your own.

I am not able to figure out exact the scenario from question, but using proper locking strategy might resolve the issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM