AtomicInteger 的使用
为什么需要java.util.concurrent.atomic.AtomicInteger
++i,–i 不是线程安全的,涉及到三步,1、获取 i 值 2、进行运算 3、写回新值 。多线程情况下,结果超出预期。
AtomicInteger 提供了哪些方法
代码注释里标明了提供的方法。边使用,边熟悉。
import static org.junit.Assert.*;
import java.util.concurrent.atomic.AtomicInteger;
public class Test {
public static void main(String args[]) throws InterruptedException {
final AtomicInteger value = new AtomicInteger(10);
//获取值
assertEquals(value.get(),10);
//设置值
value.set(5);
assertEquals(value.get(),5);
//比较并设置
// 当前跟预期比较,不相等不更新。
assertEquals(value.compareAndSet(3, 2), false);
assertEquals(value.get(), 5);
// 当前跟预期比较,相等更新。
assertEquals(value.compareAndSet(5, 2), true);
assertEquals(value.get(), 2);
//++i
assertEquals(value.incrementAndGet(), 3);
//+n
assertEquals(value.getAndAdd(5),3);
assertEquals(value.get(),8);
//i++
assertEquals(value.getAndIncrement(),8);
assertEquals(value.get(),9);
//+n
assertEquals(value.addAndGet(2),11);
//--i
assertEquals(value.decrementAndGet(),10);
//i--
assertEquals(value.getAndDecrement(),10);
assertEquals(value.get(),9);
//i==n
assertEquals(value.getAndSet(6),9);
assertEquals(value.get(),6);
}
}
验证AtomicInteger 线程安全
import java.util.concurrent.atomic.AtomicInteger;
import static org.junit.Assert.assertEquals;
class Test {
static int ivalue = 10;
public static void main(String args[]) throws InterruptedException {
//使用 AtomicInteger,线程安全
//普通的 ++i,线程不安全
final AtomicInteger value = new AtomicInteger(10);
final int threadSize = 50000;
Thread[] t = new Thread[threadSize];
for(int i=0;i<threadSize;i++){
t[i] = new Thread(){
@Override
public void run(){
value.incrementAndGet();
++ivalue;
}
};
}
for(Thread tt :t){
tt.start();
}
for(Thread tt: t){
tt.join();
}
assertEquals(value.get(),threadSize+10);//true
assertEquals(ivalue,threadSize+10);//线程足够多时,false
}
}