I need to implement global object collecting statistics for web server. I have Statistics
singleton, which has method addSample(long sample)
, which subsequently call updateMax
. This has to be obviously thread-safe. I have this method for updating maximum of whole Statistics:
AtomicLong max; private void updateMax(long sample) { while (true) { long curMax = max.get(); if (curMax < sample) { boolean result = max.compareAndSet(curMax, sample); if (result) break; } else { break; } } }
Is this implementation correct? I am using java.util.concurrent, because I believe it would be faster than simple synchronized
. Is there some other / better way to implement this?
A data type or static method is threadsafe if it behaves correctly when used from multiple threads, regardless of how those threads are executed, and without demanding additional coordination from the calling code.
A thread-safe variant of ArrayList in which all mutative operations (e.g., add, set, remove..) are implemented by creating a separate copy of an underlying array. It achieves thread safety by creating a separate copy of the List which is different than vector or other collections used to provide thread-safety.
The collection classes that are thread-safe in Java are Stack, Vector, Properties, Hashtable, etc.
In order to be thread safe you must declare the variable as follows: public static volatile int value; Now value being volatile, will be accessed in a synchronized block. Making the variable volatile is different from accessing it from a synchronized block.
As of Java 8, LongAccumulator has been introduced. It is advised as
This class is usually preferable to AtomicLong when multiple threads update a common value that is used for purposes such as collecting statistics, not for fine-grained synchronization control. Under low update contention, the two classes have similar characteristics. But under high contention, expected throughput of this class is significantly higher, at the expense of higher space consumption.
You can use it as follows:
LongAccumulator maxId = new LongAccumulator(Long::max, 0); //replace 0 with desired initial value maxId.accumulate(newValue); //from each thread
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