Java中的AtomicInteger示例

时间:2020-01-09 10:35:13  来源:igfitidea点击:

Java中的java.util.concurrent.atomic软件包具有支持无锁原子操作的类。这意味着,对于整数,长整数,布尔值以及对象引用和数组,无需使用显式同步或者锁定,就可以保证使用该程序包中包含的类的原子性。在本文中,我们将讨论Java中的此类AtomicInteger之一,该类提供可以自动更新的int值。

Java中的AtomicInteger

AtomicInteger类是java.util.concurrent.atomic包的一部分,提供了获取,设置,递增,更新,比较int值的方法,该方法作为原子操作,也无需使用锁或者synced关键字来调节多个线程对共享变量的访问。

原子类使用CAS(比较和交换)来确保使用非阻塞算法的数据完整性。这就是为什么这些类比锁定快的原因,在一个线程获得对象锁定而其他线程被阻塞的情况下,锁定比锁定快。

Java AtomicInteger构造函数

AtomicInteger类中有两个构造函数。

  • AtomicInteger()–创建一个初始值为0的新AtomicInteger。

  • AtomicInteger(int initialValue)–创建一个使用给定初始值初始化的新AtomicInteger。

AtomicInteger Java示例

常见用途之一是使用AtomicInteger提供原子递增计数器。为了这个目的,可以使用incrementAndGet()方法来原子地增加当前值。

使用AtomicInteger以原子方式递增的计数器

public class AtomicIntExample {
  public static void main(String[] args) {
    ExecutorService executor = Executors.newFixedThreadPool(2);
    AtomicInteger atomicInt = new AtomicInteger();
    for(int i = 0; i < 10; i++){
      executor.submit(()->System.out.println("Counter- " + atomicInt.incrementAndGet()));
    }
    executor.shutdown();
  }
}

输出:

Counter- 1
Counter- 2
Counter- 3
Counter- 4
Counter- 5
Counter- 6
Counter- 7
Counter- 8
Counter- 9
Counter- 10

在上面的示例中,Runnable被实现为lambda表达式。如果我们更喜欢Runnable实现,则这里的旧方法是同一示例。

public class AtomicIntExample {
  public static void main(String[] args) {
    ExecutorService executor = Executors.newFixedThreadPool(2);
    AtomicInteger atomicInt = new AtomicInteger();
    CounterRunnable runnableTask = new  CounterRunnable(atomicInt);
    for(int i = 0; i < 10; i++){
      executor.submit(runnableTask);
    }
    executor.shutdown();
  }
}

class CounterRunnable implements Runnable{
  AtomicInteger atomicInt;
  CounterRunnable(AtomicInteger atomicInt){
    this.atomicInt = atomicInt;
  }
  @Override
  public void run() {
    System.out.println("Counter- " + atomicInt.incrementAndGet());		
  }
}

AtomicInteger类中的方法

Java AtomicInteger类中的一些原子方法如下:

  • addAndGet(int delta)–以原子方式将给定值添加到当前值。

  • compareAndSet(int Expect,int update)–如果当前值==预期值,则以原子方式将该值设置为给定的更新值。

  • getAndDecrement()–以原子方式将当前值减一。

  • getAndIncrement()–以原子方式将当前值增加一。

  • getAndSet(int newValue)–以原子方式设置为给定值并返回旧值。

  • getAndUpdate(IntUnaryOperator updateFunction)–使用应用给定函数的结果以原子方式更新当前值,并返回先前的值。

  • IncrementAndGet()–以原子方式将当前值增加一。

使用AtomicInteger比较和设置值

我们可以使用compareAndSet()方法比较并设置值,该方法接受两个参数的期望值并进行更新。如果期望值等于AtomicInteger实例的当前值,则将更新该值。如果成功,则返回true。错误返回表示实际值不等于期望值。

public class AtomicIntExample {
  public static void main(String[] args) {
    ExecutorService executor = Executors.newFixedThreadPool(2);
    AtomicInteger atomicInt = new AtomicInteger(0);
    
    for(int i = 1; i <= 10; i++){
      // delay between each update submission
      try {
        TimeUnit.MILLISECONDS.sleep(20);
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      executor.submit(new RunnableTask(atomicInt, atomicInt.get(), i));
    }
    System.out.println("Updated value- " + atomicInt.get());
    executor.shutdown();
  }
}

class RunnableTask implements Runnable{
  AtomicInteger atomicInt;
  int expectedVal;
  int newVal;
  RunnableTask(AtomicInteger atomicInt, int expectedVal, int newVal){
    this.atomicInt = atomicInt;
    this.expectedVal = expectedVal;
    this.newVal = newVal;
  }
  @Override
  public void run() {
    System.out.println("Value updated- " + atomicInt.compareAndSet(expectedVal, newVal));		
  }
}

输出:

Value updated- true
Value updated- true
Value updated- true
Value updated- true
Value updated- true
Value updated- true
Value updated- true
Value updated- true
Value updated- true
Value updated- true
Updated value- 10