搜文章
推荐 原创 视频 Java开发 iOS开发 前端开发 JavaScript开发 Android开发 PHP开发 数据库 开发工具 Python开发 Kotlin开发 Ruby开发 .NET开发 服务器运维 开放平台 架构师 大数据 云计算 人工智能 开发语言 其它开发
Lambda在线 > 我的IT技术路 > java并发--聊聊java自带的原子更新类

java并发--聊聊java自带的原子更新类

我的IT技术路 2020-06-12

在多并发中,原子性是一个基本的特性,如何高效的保证原子性操作是一个比较复杂的过程,还好在java语言中,jdk提供了atomic包,在该包中定义了几类原子性更新的。本文就对这些原子更新类做个小结,至于具体源码分析可以参考之前的jdk源码系列的文章,这里不再赘述。

jdk中,大概可以把atomic包分为以下几类:

 

针对特定类型的更新

AtomicBooleanAtomicIntegerAtomicLongAtomicReference,这一类的更新在更新之前就定义好了要更新的内容就是一个特定的类型,比如Boolean类型,integer类型等。对于这种类型的使用,可以说是比较简单,其使用方法基本一致,下面我们通过一个demo描述一下。

1. public class AtomicIntegerTest {  

2.     public static void main(String[] args) {  

3.         AtomicInteger  integer = new AtomicInteger(0);//定义好一个整型变量  

4.         for (int i =0;i<100;i++){  

5.             new Thread(new AddTest(integer)).start();  

6.         }  

7.     }  

8.   

9.     private static class AddTest implements Runnable{  

10.         private AtomicInteger data ;  

11.         public AddTest(AtomicInteger a) {  

12.             this.data = a;  

13.         }  

14.   

15.         @Override  

16.         public void run() {  

17.             System.out.println(Thread.currentThread().getName()+" get data is "  

18.                     +data.addAndGet(1));  

19.         }  

20.     }  

21. }  

特定类型数组的更新:

这类是更新的是一个数组结构,不像上面一样,只能更新一个。这类包括以下几个类型,AtomicIntegerArrayAtomicLongArrayAtomicReferenceArray,当然了其使用模式也和上面的类似,我们也通过一个demo来说明一下。

1. public class AtomicIntegerArrayTest {  

2.     public static void main(String[] args) {  

3.         AtomicIntegerArray array = new AtomicIntegerArray(1);//定义一个数组  

4.         for (int i =0;i<100;i++){  

5.             new Thread(new AddTest(array)).start();  

6.         }  

7.     }  

8.     private static class AddTest implements Runnable{  

9.         private AtomicIntegerArray data ;  

10.         public AddTest(AtomicIntegerArray a) {  

11.             this.data = a;  

12.         }  

13.         @Override  

14.         public void run() {  

15.             System.out.println(Thread.currentThread().getName()+" get array[0] is "  

16.                     +data.addAndGet(0,1));  

17.         }  

18.     }  

19. }  

 

更新某个类中的特定类型的变量:

这类是和之前的不太一样,这个类是更新某个类中的特定的元素,换句话说这个原子更新的变量是某个类中的一个成员变量。该类中的有:AtomicIntegerFieldUpdaterAtomicLongFieldUpdaterAtomicReferenceFieldUpdater

这类在使用上和之前的稍微有点不同,其定义的变量需要满足public权限,需要设置成volatile修饰,满足这两点的话,是可以使用原子整型更新器的。下面我们通过一个demo来说明一下:

1. public class AtomicIntegerFieldUpdaterTest {  

2.     private static final AtomicIntegerFieldUpdater<Fruit> updater = AtomicIntegerFieldUpdater.newUpdater(Fruit  

3.             .class,"price");//定义price是需要更新的变量  

4.     public static void main(String[] args) {  

5.         Fruit fruit = new Fruit(1,"apple");  

6.         for (int i =0;i<100;i++){  

7.             new Thread(new AddTest(fruit)).start();  

8.         }  

9.     }  

10.     private static class AddTest implements Runnable{  

11.         private Fruit f ;  

12.         public AddTest(Fruit f) {  

13.             this.f = f;  

14.         }  

15.   

16.         @Override  

17.         public void run() {  

18.             System.out.println(Thread.currentThread().getName()+" get data is "  

19.                     +updater.addAndGet(f,1));  

20.         }  

21.     }  

22.     private static class Fruit{  

23.         public volatile int price;//访问权限要public ,设置成volatile变量,以保证变量的操作可见  

24.         private String name;  

25.   

26.         public Fruit(int price, String name) {  

27.             this.price = price;  

28.             this.name = name;  

29.         }  

30.   

31.         public int getPrice() {  

32.             return price;  

33.         }  

34.   

35.         public void setPrice(int price) {  

36.             this.price = price;  

37.         }  

38.   

39.         public String getName() {  

40.             return name;  

41.         }  

42.   

43.         public void setName(String name) {  

44.             this.name = name;  

45.         }  

46.     }  

47. }  

 

累加器和计数器:

累加器和计数器是为了优化之前的原子更新器而添加的,在该类别中,主要是实现累加或者其他计数功能的。该类中主要是以下几个:LongAccumulatorLongAdderDoubleAdderDoubleAccumulator。那么该类的使用方法我们也通过一个demo看下:

1. public class LongAccumulatorTest {  

2.     public static void main(String[] args) {  

3.         LongAccumulator longAccumulator = new LongAccumulator((x,y)->x*y,1);///自定义计算方法  

4.         IntStream.range(0,10).forEach(i->  

5.                 new Thread(new AddTest(longAccumulator)).start());  

6.     }  

7.   

8.     private static class AddTest implements Runnable{  

9.         private LongAccumulator adder;  

10.         public AddTest(LongAccumulator adder) {  

11.             this.adder = adder;  

12.         }  

13.         @Override  

14.         public void run() {  

15.             adder.accumulate(2);  

16.             System.out.println(Thread.currentThread().getName()+" get sum is "+adder.get());  

17.         }  

18.     }  

19. }  

在实际中,我们还是比较经常使用原子性操作来保证多线程下的安全,其原理的话,之前的文章介绍了主要是CAS,使用的话,也相对比较简单。


版权声明:本站内容全部来自于腾讯微信公众号,属第三方自助推荐收录。《java并发--聊聊java自带的原子更新类》的版权归原作者「我的IT技术路」所有,文章言论观点不代表Lambda在线的观点, Lambda在线不承担任何法律责任。如需删除可联系QQ:516101458

文章来源: 阅读原文

相关阅读

关注我的IT技术路微信公众号

我的IT技术路微信公众号:gh_cb12c84e6957

我的IT技术路

手机扫描上方二维码即可关注我的IT技术路微信公众号

我的IT技术路最新文章

精品公众号随机推荐