1.AtomicInteger原子类
改写上一节我们使用的代码(上一节:https://blog.csdn.net/qq_35688140/article/details/100629270)
此时我们将上一节的int变成了AtomicInteger:
@ThreadSafe
public class CountExample2 {
// 请求总数
public static int clientTotal = 5000;
// 同时并发执行的线程数
public static int threadTotal = 200;
public static AtomicInteger count = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);// 使用信号量控制并发数
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);//保证所有线程执行完成后执行某操作
for (int i = 0; i < clientTotal ; i++) {
executorService.execute(()->{
try{
semaphore.acquire();//获取信号量
add();
semaphore.release();//释放信号量
}catch (Exception e){
log.info("exception",e);
}
countDownLatch.countDown();//每次执行一个循环,计算器减少一次
});
}
countDownLatch.await();//等待计数器变为0
executorService.shutdown();//关闭线程池
log.info("count:"+count);
}
// count++方法
public static void add(){
count.incrementAndGet();
}
}
运行效果:多次运行都是5000,表明这是一个线程安全类
核心方法:while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4))有一个自旋锁,不断的比较var2与var5的值,一旦相等就将v1更新成var5+var4
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
2.LongAdder
LongAdder会将整个数据分离成一个数组,提高数据的计算效率和并行度。而且对于热点数据会分散为多个cell,所有cell累加求和等到最终结果。相当于将单点的更新压力分散到多个点上。在低并发时,通过对base的直接更新来提高性能。
并发低:直接使用atomic效率更高。
并发高:使用LongAdder高率高,但是并发时可能导致数据有误差。
@ThreadSafe
public class AtomicExample3 {
// 请求总数
public static int clientTotal = 5000;
// 同时并发执行的线程数
public static int threadTotal = 200;
public static LongAdder count = new LongAdder();//默认初始值为0
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);// 使用信号量控制并发数
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);//保证所有线程执行完成后执行某操作
for (int i = 0; i < clientTotal ; i++) {
executorService.execute(()->{
try{
semaphore.acquire();//获取信号量
add();
semaphore.release();//释放信号量
}catch (Exception e){
log.info("exception",e);
}
countDownLatch.countDown();//每次执行一个循环,计算器减少一次
});
}
countDownLatch.await();//等待计数器变为0
executorService.shutdown();//关闭线程池
log.info("count:"+count);
}
// count++方法
public static void add(){
count.increment();
}
}
结果:
3.AtomicBoolean
通过AtomicBoolean 可以在并发条件下,让某个过程只执行一次。
public class AtomicExample6 {
private static AtomicBoolean atomicBoolean = new AtomicBoolean(false);
// 请求总数
public static int clientTotal = 5000;
// 同时并发执行的线程数
public static int threadTotal = 200;
public static AtomicInteger count = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);// 使用信号量控制并发数
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);//保证所有线程执行完成后执行某操作
for (int i = 0; i < clientTotal ; i++) {
executorService.execute(()->{
try{
semaphore.acquire();//获取信号量
test();
semaphore.release();//释放信号量
}catch (Exception e){
log.info("exception",e);
}
countDownLatch.countDown();//每次执行一个循环,计算器减少一次
});
}
countDownLatch.await();//等待计数器变为0
executorService.shutdown();//关闭线程池
log.info("ishappened:"+atomicBoolean.get());
}
// count++方法
public static void test(){
if(atomicBoolean.compareAndSet(false,true)){
log.info("execute");
}
}
}
结果: