I intend to create a realtime counter. So one user can incremenet the counter value for specific key. Whilst another gets the updated count value via an ajax request (either in a loop, or using some long polling method). I will use a spring controller, which will inject the service class can I do something like below, or is there a better way :
@Service
public MyService{
//instance variable in spring injected service class, not sure if this correct
static final Map<String, Integer> myMap;
public void add(String key){
Integer count = myMap.get(key);
count++;
myMap.put(key, count);
}
//accessed via ajax loop (and controller), if value changes update display
public Integer getCount(String key){
return myMap.get(key)
}
@PostConstruct
public load(){
myMap = new HashMap<String, Integer>(10){{//initialize}};
}
Edit there are a few answers but it is not clear which is the best : Synchronize the add method ? Create map in another class(annotated repository) and inject that ? Something else ?
You can, but need to be aware of those problems:
The Integer class is immutable. This means that you can't make modifications to it. So, in order to increment the count, you have to put it back into the map after you've incremented it:
public void add(String key){
Integer count = myMap.get(key);
count++;
myMap.put(key, count);
}
A problem that this introduces is thread safety. If this service class is going to be accessed by multiple threads at the same time, then you have to make sure its data is accessed in a safe way. Since the myMap is being modified, and because the HashMap class is not thread-safe, you have to make it thread-safe. One way you can do this is to use the Collections.synchronizedMap() method. This will automatically make a Map instance thread-safe.
@PostConstruct
public load(){
myMap = new HashMap<String, Integer>(10){{//initialize}};
myMap = Collections.synchronizedMap(myMap);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With