Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: map of concurrently incremented counters

I need to implement a map of counters (like Map) in my application. However this structure is supposed to be accessed by several threads.

It looks like ConcurrentHashMap<Key, Long> is not a proper solution, right?

I thought about ConcurrentHashMap<Key, AtomicLong> instead.

But there is a problem - requests for increment are not spread evenly. Few most popular Keys could have up to 95% of all increment requests to this data structure.

As far as I understand this will lead to concurrent access to single AtomicLong instances and there many locks should occur which will somewhat decrease efficiency.

Question 1: Is there any better solution - perhaps, better data type instead of AtomicLong, which allows short accumulation of increments or something like this?

Question 2: I want to persist the structure to disk periodically (perhaps, every minute), and I want to persist its "actual" state (with all recent updates settled?) - what is most straightforward way for it?

like image 493
Rodion Gorkovenko Avatar asked Feb 21 '26 21:02

Rodion Gorkovenko


1 Answers

What makes you think AtomicLong uses locks internally? That is not true, it's mostly built on CAS operations. My advice would be to implement it with AtomicLong and profile the implementation later. If (and only if) your counter will be a bottleneck, then consider replacing it with any other implementation.

"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil" - Donald Knuth

As of state persistence the simplest approach is to serialize your map:

ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream objOut = new ObjectOutputStream(out);
objOut.writeObject(map);
objOut.close();
like image 93
Jk1 Avatar answered Feb 24 '26 11:02

Jk1



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!