一、AtomicInteger等
Atomic是一系列原子类:
* AtomicInteger,AtomicLong,AtomicReference,AtomicIntegerArray...。
* 内部实现原理是:循环CAS。
public class AtomicBaseDemo {
public static void main(String[] args) throws InterruptedException {
//一、Api基本使用
AtomicInteger atomicInt = new AtomicInteger(1);
int incrementAndGet = atomicInt.incrementAndGet();
boolean compareAndSet = atomicInt.compareAndSet(3, 11); // 此时预期应该是2
System.out.println(compareAndSet); // false
System.out.println(atomicInt.compareAndSet(2, 10)); // true
System.out.println(atomicInt.get()); // 10
System.out.println(atomicInt.getAndAdd(10)); // 10,返回10,实际值是20
System.out.println(atomicInt.getAndSet(5)); // 20, 返回5,实际值是5.
//二、案例
atomicInt.set(0);
final int threadSize = 1000;
Thread[] ts = new Thread[threadSize];
for (int i = 0; i < threadSize; i++) {
ts[i] = new Thread() {
public void run() {
atomicInt.incrementAndGet();
}
};
}
for (Thread t : ts) {
t.start();
}
for (Thread t : ts) {
t.join();
}
System.out.println(atomicInt.get()); // 1000
}
}
二、AtomicReference
概述:原子数组主要由AtomicIntegerArray/AtomicLongArray这些包装类
* 主要Api方法:getAndIncrement(index),即比AtomicInteger多了一个index参数
public class ArrayAtomicDemo {
private static int THREADCOUNT = 1000;
private static CountDownLatch countDown = new CountDownLatch(THREADCOUNT);
private static int[] values = new int[10];
private static AtomicIntegerArray atomicValues = new AtomicIntegerArray(values);
public static void main(String[] args) throws InterruptedException {
// 1、1000个线程,每个线程循环100次,每次每个元素+1
for (int i = 0; i < THREADCOUNT; i++) {
new Thread(()->{
for (int j = 0; j < 100; j++) {
for (int k = 0; k < values.length; k++) {
values[k]++;
}
}
countDown.countDown();
}).start();
}
countDown.await();
for (int i = 0; i < 10; i++) {
System.out.print(values[i]+" ");
}
//99873 99878 99872 99868 99863 99856 99868 99862 99851 99853
System.out.println();
// 2、1000个线程,每个线程循环100次,每次每个元素+1,使用AtomicIntegerArray。
countDown = new CountDownLatch(THREADCOUNT);
for (int i = 0; i < THREADCOUNT; i++) {
new Thread(()->{
for (int j = 0; j < 100; j++) {
for (int k = 0; k < values.length; k++) {
atomicValues.getAndIncrement(k);
}
}
countDown.countDown();
}).start();
}
countDown.await();
for (int i = 0; i < 10; i++) {
System.out.print(atomicValues.get(i)+" ");
}
//100000 100000 100000 100000 100000 100000 100000 100000 100000 100000
}
}
三、AtomicReference
* AtomicReference引用原子包装类
* 概述:AtomicInteger是对int,AtomicIntegerArray是对数组的一些CAS操作api的集合,
* 那么AtomicReference就是包装引用类型,比如compareAndSet(expect,update)。它有一个
* 泛型,可以指定被包装引用的类型。下面是模拟并发栈。
public class AtomicReferenceDemo<E> {
AtomicReference<Node<E>> first = new AtomicReference<Node<E>>();
public void push(E e){
Node<E> newHead = new Node<E>(e);
Node<E> oldHead;
for (;;) {
oldHead = first.get(); /**内部是原子变量*/
newHead.next = oldHead;
if(first.compareAndSet(oldHead, newHead)){ /**利用本地方法的cas操作*/
break;
}
}
}
public E pop(){
Node<E> oldHead;
Node<E> newHead;
do {
oldHead = first.get();
if (oldHead == null)
return null;
newHead = oldHead.next;
} while (!first.compareAndSet(oldHead, newHead));
return oldHead.item;
}
private static class Node<E>{
final E item;
Node<E> next; /**因为都是一端进行操作,所以next不用Atomic包装!*/
public Node(E item) {
this.item = item;
}
}
}