jdk源码解析--LongAdder类
Posted 我的IT技术路
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jdk源码解析--LongAdder类相关的知识,希望对你有一定的参考价值。
在之前介绍的抽象类Striped64中,我们知道这个类是为了计数器而设计的,在jdk中有LongAdder,LongAccumulator,DoubleAdder,DoubleAccumulator四个类继承了Striped64类,以**Adder为结尾的是累加器,实现的是一种以初始值为0的累加效果,而以**Accumulator为结尾的是计数器,有着更灵活的操作,初始值不一定为0,实现的方式也不一定是累加,亦可以是相乘等其他操作。换句话说累加器是计数器的一种特殊实现。本文主要讲解的是LongAdder。现在我们通过一个demo来看下累加器的应用。
1. import java.util.concurrent.atomic.LongAdder;
2. import java.util.stream.IntStream;
3.
4. public class LongAdderTest {
5.
6. public static void main(String[] args) {
7. LongAdder longAdder = new LongAdder();
8. IntStream.range(0,100).forEach(i->
9. new Thread(new AddTest(longAdder)).start());
10. }
11.
12. private static class AddTest implements Runnable{
13. private LongAdder adder;
14.
15. public AddTest(LongAdder adder) {
16. this.adder = adder;
17. }
18.
19. @Override
20. public void run() {
21. adder.add(1);//这个是原子性的,能保证最后累加的结果是正确的
22. System.out.println(Thread.currentThread().getName()+" get sum is "+adder.sum());//这个是返回当前的总和,是一个当前线程获取到的一个快照
23. }
24. }
25. }
看上去和AtomicLong的的使用没什么差别,但在多线程高并发的情况下效率上会比较高。
下面我们可以看下这个类的具体实现:
1. public class LongAdder extends Striped64 implements Serializable {
2. private static final long serialVersionUID = 7249069246863182397L;
3. public LongAdder() {
4. }
5. public void add(long x) {
6. Cell[] as; long b, v; int m; Cell a;
7. if ((as = cells) != null || !casBase(b = base, b + x)) {//cas设置base操作不成功
8. boolean uncontended = true;
9. if (as == null || (m = as.length - 1) < 0 ||//as为空或者长度小于0
10. (a = as[getProbe() & m]) == null || //或者该位置为空
11. !(uncontended = a.cas(v = a.value, v + x)))//是否发生竞争
12. longAccumulate(x, null, uncontended);
13. }
14. }
15. public void increment() {
16. add(1L);
17. }
18. public void decrement() {
19. add(-1L);
20. }
21. public long sum() {//获取当前的值,没有加锁,只是获取当时的快照值
22. Cell[] as = cells; Cell a;
23. long sum = base;
24. if (as != null) {
25. for (int i = 0; i < as.length; ++i) {
26. if ((a = as[i]) != null)
27. sum += a.value;
28. }
29. }
30. return sum;
31. }
32. public void reset() {//重置
33. Cell[] as = cells; Cell a;
34. base = 0L;
35. if (as != null) {
36. for (int i = 0; i < as.length; ++i) {
37. if ((a = as[i]) != null)
38. a.value = 0L;
39. }
40. }
41. }
42. public long sumThenReset() {//求和后重置,返回求和后的值
43. Cell[] as = cells; Cell a;
44. long sum = base;
45. base = 0L;
46. if (as != null) {
47. for (int i = 0; i < as.length; ++i) {
48. if ((a = as[i]) != null) {
49. sum += a.value;
50. a.value = 0L;
51. }
52. }
53. }
54. return sum;
55. }
56.
57. }
上面的实现还是比较简单,核心在上一文中的Striped64中介绍。本文就介绍到这里,下一节我们看下计数器的实现。
以上是关于jdk源码解析--LongAdder类的主要内容,如果未能解决你的问题,请参考以下文章