并发库应用之二 & Java原子性操作类应用

  Java5的线程并发库中,提供了一组atomic class来帮助我们简化同步处理。基本工作原理是使用了同步synchronized的方法实现了对一个long, integer, 对象的增、减、赋值(更新)操作

       java.util.concurrent在并发编程中很常用的实用工具类。

                     |----locks为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器

                     |----atomic类的小工具包,支持在单个变量上解除锁的线程安全编程。可以对基本类型、数组中的基本类型、类中的基本类型等进行操作

                            |----AtomicInteger  用于提供整型数字原子性操作

           |----AtomicIntegerArray  用于提供整型数组原子性操作

           |----AtomicIntegerFieldUpdater  用于提供类对象中的整型数据原子性操作

           ......  对应有Double...相类似的原子性操作类

  以上原子性操作类具体如何使用详情可以查看相应的官方jdk文档,下面通过简单的两个例子的对比来看一下 AtomicInteger 的强大的功能,分别是普通的方法与使用AtomicInteger类的方法:

普通方法实现方案:

 1 public class CommonTest {
 2     private volatile int count = 0; //volatile关键字实现线程间数据共享
 3 
 4     public synchronized void increment() {
 5        count++; //若要线程安全执行,需要加锁
 6     }
 7 
 8     public int getCount() {
 9         return count;
10     }
11 }

使用AtomicInteger类的方法实现

 1 public class AtomicIntegerTest {
 2     private AtomicInteger count = new AtomicInteger();
 3 
 4     public synchronized void increment() {
 5         count.incrementAndGet();
 6     }
 7 
 8     public int getCount() {
 9         return count.get();
10     }
11 }

调用两个类的主方法实现

 1 public class MainClass {    
 2     public static void main(String[] args) {
 3         //final CommonTest atomicIntegerTest = new CommonTest();
 4         final AtomicIntegerTest atomicIntegerTest = new AtomicIntegerTestTrue();
 5         for (int j = 0; j < 3; j++) { //各自同时开启3个线程
 6             //增加线程
 7             new Thread(new Runnable() {
 8                 @Override
 9                 public void run() {
10                     for (int i = 0; i < 10; i++) {
11                         atomicIntegerTest.increment();
12                         try {
13                             Thread.sleep(1000);
14                         } catch (InterruptedException e) {
15                             e.printStackTrace();
16                         }
17                     }
18                 }
19             }).start();
20             //读取线程
21             new Thread(new Runnable() {
22                 @Override
23                 public void run() {
24                     for (int i = 0; i < 10; i++) {
25                         System.out.println(Thread.currentThread().getName() + "-->" + atomicIntegerTest.getCount());
26                         try {
27                             Thread.sleep(1000);
28                         } catch (InterruptedException e) {
29                             e.printStackTrace();
30                         }
31                     }
32                 }
33             }).start();
34         }
35     }
36 }

运行结果如下所示:

Thread-1-->1
Thread-3-->2
Thread-5-->3
Thread-3-->4
Thread-1-->5
Thread-5-->5
Thread-1-->9
Thread-5-->9
Thread-3-->9
Thread-5-->12
Thread-3-->12
Thread-1-->12
Thread-3-->13
Thread-1-->13
Thread-5-->14
Thread-5-->16
Thread-1-->16
Thread-3-->16
Thread-1-->21
Thread-3-->21
Thread-5-->21
Thread-5-->22
Thread-1-->22
Thread-3-->22
Thread-1-->25
Thread-5-->25
Thread-3-->25
Thread-3-->29
Thread-1-->30
Thread-5-->29

  从上面的例子中我们可以看出:使用AtomicInteger是非常的安全的

  那么为什么不使用记数器自加呢,例如count++这样的,因为这种计数是线程不安全的,高并发访问时统计会有误,而AtomicInteger为什么能够达到多而不乱,处理高并发应付自如呢?

  这是由硬件提供原子操作指令实现的。在非激烈竞争的情况下,开销更小,速度更快。

提示:常用基本类的原子操作讲解完毕,接下来我们就开始进入有关多线程线程池相关概念讲解,具体详情请查看我的下一篇博客:并发库应用之三 & 线程池与定时器应用

 

posted @ 2017-03-07 23:54  星火燎原智勇  阅读(426)  评论(0编辑  收藏  举报