一、对比
在高并发的情况下整形数值自增并不是线程安全的,在双11抢购是发统计某网页浏览量,这时可以用到原子更新整形AtomicInteger。
先看个例子:
public class TestAtomicInteger {
static int a=0;
public static void main(String args[]){
CountDownLatch countDown=new CountDownLatch(2);
AtomicInteger atomicInteger=new AtomicInteger();
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<10000000;i++){
atomicInteger.incrementAndGet();
a++;
}
countDown.countDown();
}
});
t1.start();
Thread t2=new Thread(new Runnable(){
@Override
public void run() {
for(int i=0;i<10000000;i++){
atomicInteger.incrementAndGet();
a++;
}
countDown.countDown();
}
});
t2.start();
try {
countDown.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("a= "+a);
System.out.println("atomicinteger= "+atomicInteger.get());
}
}
运行结果:
代码中CountDownLatch用于等待t1,t2线程结束,每个线程结束需要手动减,利用方法countDown()。从运行结果可以看到a++所得到的结果并不是我们期待的值。在高并发情景下其并不是安全的。
二、扩展
下面给出方法说明,源码在java.util.concurrent.atomic包下,感兴趣可以自行学习
Modifier and Type | Method and Description |
---|---|
int | accumulateAndGet(int x, IntBinaryOperator accumulatorFunction) 使用将给定函数应用于当前值和给定值的结果原子更新当前值,返回更新后的值。 |
int | addAndGet(int delta) 将给定的值原子地添加到当前值。 |
boolean | compareAndSet(int expect, int update) 如果当前值 |
int | decrementAndGet() 原子减1当前值。 |
double | doubleValue() 返回此值 |
float | floatValue() 返回此值 |
int | get() 获取当前值。 |
int | getAndAccumulate(int x, IntBinaryOperator accumulatorFunction) 使用给定函数应用给当前值和给定值的结果原子更新当前值,返回上一个值。 |
int | getAndAdd(int delta) 将给定的值原子地添加到当前值。 |
int | getAndDecrement() 原子减1当前值。 |
int | getAndIncrement() 原子上增加一个当前值。 |
int | getAndSet(int newValue) 将原子设置为给定值并返回旧值。 |
int | getAndUpdate(IntUnaryOperator updateFunction) 用应用给定函数的结果原子更新当前值,返回上一个值。 |
int | incrementAndGet() 原子上增加一个当前值。 |
int | intValue() 将 |
void | lazySet(int newValue) 最终设定为给定值。 |
long | longValue() 返回此值 |
void | set(int newValue) 设置为给定值。 |
String | toString() 返回当前值的String表示形式。 |
int | updateAndGet(IntUnaryOperator updateFunction) 使用给定函数的结果原子更新当前值,返回更新的值。 |
boolean | weakCompareAndSet(int expect, int update) 如果当前值 |