操作AtomicInteger的api

AtomicInteger位于juc的atomic包下

利用cas,进行原子更新操作

先写一个test,一起看一下这个结果

public class AtomicIntegerTest {
     

  public static void main(String[] args) {
     
    Set<Integer> set = Collections.synchronizedSet(new HashSet<>());
    AtomicInteger ai = new AtomicInteger(0);

    Thread t1 = new Thread() {
     
      int x = 0;
      @Override
      public void run() {
     
        while (x<50) {
     
          int v = ai.getAndIncrement();
          set.add(v);
          x++;
        }
      }
    };

    Thread t2 = new Thread() {
     
      int x = 0;
      @Override
      public void run() {
     
        while (x<150) {
     
          int v = ai.getAndIncrement();
          set.add(v);
          x++;
        }
      }
    };

    Thread t3 = new Thread() {
     
      int x = 0;
      @Override
      public void run() {
     
        while (x<150) {
     
          int v = ai.getAndIncrement();
          set.add(v);
          x++;
        }
      }
    };

    t1.start();
    t2.start();
    t3.start();
    try {
     
      t1.join();
      t2.join();
      t3.join();
      System.out.println(set.size());
    } catch (InterruptedException e) {
     
      e.printStackTrace();
    }
  }
}

这里最终得到的set的长度是350,如果通过i++不能准确的得到

对AtomicInteger的api进行简单的操作

class AtomicIntegerApiTestTest {
     

  @Test
  public void testCreate() {
     
    AtomicInteger ai = new AtomicInteger();
    AtomicInteger atomicInteger = new AtomicInteger(10);
    System.out.println(ai.get());
    System.out.println(atomicInteger.get());
  }

  @Test
  void testSet() {
     
    AtomicInteger atomicInteger = new AtomicInteger(10);
    // 通过set直接赋值
    atomicInteger.set(19);
    System.out.println(atomicInteger.get());
  }

  /** 结果 0 20 */
  @Test
  void testGetAndSet() {
     
    AtomicInteger atomicInteger = new AtomicInteger(0);
    final int andSet = atomicInteger.getAndSet(20);
    System.out.println(andSet);
    System.out.println(atomicInteger.get());
  }

  /** 类似于++i 结果是2 */
  @Test
  void testIncrementAndGet() {
     
    AtomicInteger atomicInteger = new AtomicInteger(1);
    System.out.println(atomicInteger.incrementAndGet());
  }

  /** 类似于i++ 结果是1 */
  @Test
  void testGetAndIncrement() {
     
    AtomicInteger atomicInteger = new AtomicInteger(1);
    System.out.println(atomicInteger.getAndIncrement());
  }

  /** getAndAdd 加任意值 结果 1 11 */
  @Test
  void testGetAndAdd() {
     
    AtomicInteger atomicInteger = new AtomicInteger(1);
    final int andAdd = atomicInteger.getAndAdd(10);
    System.out.println(andAdd);
    System.out.println(atomicInteger.get());
  }

  /** 结果 11 11 */
  @Test
  void testAddAndGet() {
     
    AtomicInteger atomicInteger = new AtomicInteger(1);
    final int andAdd = atomicInteger.addAndGet(10);
    System.out.println(andAdd);
    System.out.println(atomicInteger.get());
  }

  /**
   * 两个线程同时操作一个变量
   * i=1 i=1
   * 两个线程都看到i=1
   * i=i+1 i=i+1
   * 两个线程同时操作一个代码逻辑快
   * 上述可能同时输出 3和3
   * 可能会跳过2的操作
   *
   * 

* for(;;) { * int current = get(); * if(compareAndSet(current,newValue)) { * return current; * } * } * *

* current==value的情况下才会做交换 * 将value==newValue * 第一个线程看到的是current=1 * 但是第二个线程的所有的步骤都已经执行完成现在的current=2,value=2 * 第一个线程拿着currnet与value进行比较,current!=value即1!=2 * 进行for(;;)循环操作 current=get(),current变成2 current==value,将value设置成新的值newValue为3 */ /** 输出的结果 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 */ @Test void testThreadAddAndGet() { AtomicInteger atomicInteger = new AtomicInteger(0); new Thread() { @Override public void run() { for (int i = 0; i < 10; i++) { final int i1 = atomicInteger.addAndGet(1); System.out.println(i1); } } }.start(); new Thread() { @Override public void run() { for (int i = 0; i < 10; i++) { final int i2 = atomicInteger.addAndGet(1); System.out.println(i2); } } }.start(); } @Test void testCAS() { AtomicInteger atomicInteger = new AtomicInteger(10); final boolean b = atomicInteger.compareAndSet(12, 20); System.out.println(b); // 结果是10 ,我们期望值是12 但是当前值是10 ,所以value值不会变成20 System.out.println(atomicInteger.get()); System.out.println("========================="); final boolean b1 = atomicInteger.compareAndSet(10, 20); System.out.println(b1); // 结果是20 ,我们期望值是10 当前值是10 ,所以value值变成20 System.out.println(atomicInteger.get()); } }

注释也很重要

cas就是无限循环,直到当前值与预期值相等,然后进行数据更新

for(;;) {
     
   int current = get();
   if(compareAndSet(current,newValue)) {
     
   		return current;
    }
}

你可能感兴趣的:(多线程)