分享

java 原子量Atomic举例(AtomicReference)

 dtl乐学馆 2016-03-04

 

注意:原子操作的意义是说线程不能被中断,本身并不是线程安全的,但是调用atomic的设值方法:
compareAndSet()就是线程安全的了。
 
java并发库提供了很多原子类来支持并发访问的数据安全性,除了常用的
AtomicInteger、AtomicBoolean、AtomicLong 外还有
AtomicReference 用以支持对象的原子操作:AtomicReference<V> 可以封装引用一个V实例,
通过
  1. public final boolean compareAndSet(V expect, V update)   
可以支持并发访问,set的时候进行对比判断,如果当前值和操作之前一样则返回false,否则表示数据没有 变化,例如下面的代码
使用 AtomicReference 实现了并发计数:
  1. package test;  
  2.   
  3. import java.util.concurrent.CountDownLatch;  
  4. import java.util.concurrent.atomic.AtomicReference;  
  5.   
  6. public class TS {  
  7.     public static void main(String[] args) throws InterruptedException {  
  8.         dfasd111();  
  9.     }  
  10.   
  11.     private static AtomicReference<Integer> ar = new AtomicReference<Integer>(0);  
  12.   
  13.     public static void dfasd111() throws InterruptedException {  
  14.         int t = 100;  
  15.         final int c = 100;  
  16.         final CountDownLatch latch = new CountDownLatch(t);  
  17.         for (int i = 0; i < t; i++) {  
  18.             new Thread(new Runnable() {  
  19.                 @Override  
  20.                 public void run() {  
  21.                     for (int i = 0; i < c; i++) {  
  22.                         while (true) {  
  23.                             Integer temp = ar.get();  
  24.                             if (ar.compareAndSet(temp, temp + 1)) {  
  25.                                 break;  
  26.                             }  
  27.                         }  
  28.                     }  
  29.                     latch.countDown();  
  30.                 }  
  31.             }).start();  
  32.         }  
  33.         latch.await();  
  34.         System.out.println(ar.get()); //10000000   
  35.     }  
  36.   
  37.     public final void test() {  
  38.         System.out.println(this.getClass());  
  39.     }  
  40. }  

一、原子量实现的计数器

  1. import java.util.HashSet;  
  2. import java.util.Set;  
  3. import java.util.concurrent.ExecutorService;  
  4. import java.util.concurrent.Executors;  
  5. import java.util.concurrent.atomic.AtomicInteger;  
  6. public class AtomicCounter {  
  7.   
  8.     private AtomicInteger value = new AtomicInteger();  
  9.   
  10.     public int getValue() {  
  11.         return value.get();  
  12.     }  
  13.   
  14.     public int increase() {  
  15.         return value.incrementAndGet();// 内部使用死循环for(;;)调用compareAndSet(current, next)   
  16.         //      return value.getAndIncrement();   
  17.     }  
  18.   
  19.     public int increase(int i) {  
  20.         return value.addAndGet(i);// 内部使用死循环for(;;)调用compareAndSet(current, next)   
  21.         //      return value.getAndAdd(i);   
  22.     }  
  23.   
  24.     public int decrease() {  
  25.         return value.decrementAndGet();// 内部使用死循环for(;;)调用compareAndSet(current, next)   
  26.         //      return value.getAndDecrement();   
  27.     }  
  28.   
  29.     public int decrease(int i) {  
  30.         return value.addAndGet(-i);// 内部使用死循环for(;;)调用compareAndSet(current, next)   
  31.         //      return value.addAndGet(-i);   
  32.     }  
  33.   
  34.     public static void main(String[] args) {  
  35.         final AtomicCounter counter = new AtomicCounter();  
  36.         ExecutorService service = Executors.newCachedThreadPool();  
  37.         for (int i = 0; i < 10; i++) {  
  38.             service.execute(new Runnable() {  
  39.                 @Override  
  40.                 public void run() {  
  41.                     System.out.println(counter.increase());  
  42.                 }  
  43.             });  
  44.         }  
  45.         service.shutdown();  
  46.     }  
  47. }  

二、原子量实现的银行取款

  1. import java.util.Random;  
  2. import java.util.concurrent.ExecutorService;  
  3. import java.util.concurrent.Executors;  
  4. import java.util.concurrent.atomic.AtomicLong;  
  5. public class Account {  
  6.   
  7.     private AtomicLong balance;  
  8.   
  9.     public Account(long money) {  
  10.         balance = new AtomicLong(money);  
  11.         System.out.println("Total Money:" + balance);  
  12.     }  
  13.   
  14.     public void deposit(long money) {  
  15.         balance.addAndGet(money);  
  16.     }  
  17.   
  18.     public void withdraw(long money) {  
  19.         for (; ; ) {//保证即时同一时间有人也在取款也可以再次尝试取款,如果不需要并发尝试取款,可以去掉这句   
  20.             long oldValue = balance.get();  
  21.             if (oldValue < money) {  
  22.                 System.out.println(Thread.currentThread().getName() + " 余额不足! 余额:" + balance);  
  23.                 break;  
  24.             }  
  25.             try {Thread.sleep(new Random().nextInt(1000));} catch (Exception e) { }// 模拟取款时间   
  26.             if (balance.compareAndSet(oldValue, oldValue - money)) {  
  27.                 System.out.println(Thread.currentThread().getName() + " 取款 " + money + " 成功! 余额:" + balance);  
  28.                 break;  
  29.             }  
  30.             System.out.println(Thread.currentThread().getName() + " 遇到并发,再次尝试取款!");  
  31.         }  
  32.     }  
  33.   
  34.     public static void main(String[] args) {  
  35.         final Account account = new Account(1000);  
  36.         ExecutorService pool = Executors.newCachedThreadPool();  
  37.         int i = 0;  
  38.         while (i++ < 13) {  
  39.             pool.execute(new Runnable() {  
  40.                 @Override  
  41.                 public void run() {  
  42.                     account.withdraw(100);  
  43.                 }  
  44.             });  
  45.         }  
  46.         pool.shutdown();  
  47.     }  
  48. }  


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多