并发编程(四):atomic

 本篇博客我们主要讲述J.U.C包下的atomic包,在上篇博客“并发模拟”的最后,我们模拟高并发的情形时出现了线程安全问题,怎么解决呢?其实解决的办法有很多中,如直接在add()方法上加synchronized关键字,还有一种就是用atomic包下的类来解决这个问题,这也是现在比较推荐的一种写法,下面我们给出完整代码:

复制代码
@Slf4j public class CountExample2 {      //请求总数    public static int clientTotal = 5000;     //同时并发执行的线程数    public static int threadTotal = 200;      public static AtomicInteger count = new AtomicInteger(0);      private  static void add() {         count.incrementAndGet(); //        count.getAndIncrement();    }      public static void main(String[] args)throws Exception {          //定义线程池        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.error("exception",e);                 }                 countDownLatch.countDown();             });         }         countDownLatch.await();         executorService.shutdown();         log.info("count:{}",count.get());     } }
复制代码

输出结果如下:

  由输出结果可知,我们已经保证了线程安全(如果对此demo有不解的地方可参考“并发编程(三)”),在这个demo中就是AtomicInteger发挥了作用,下面我们来系统的了解一下atomic包下的类。

 

  atomic包

  java8中,在atomic包中一共有17个类,其中有12个类是jdk1.5提供atomic时就有的,5个类是jdk1.8新加的。在原有的12个类中包含四种原子更新方式,分别是原子更新基本类型,原子更新数组,原子更新引用,原子更新字段(下面我会在每种类型中,选择某个类为代表以代码进行演示)

 java8新增的5个类分别是Striped64,LongAdder,LongAccumulator,DoubleAdder,DoubleAccumulator,Sriped64作为父类,其余四个类继承此类,分别是long和double的具体实现

 

  原子更新基本类型

  通过原子的方式更新基本类型。以AtomicInteger为代表进行演示

  AtomicInteger的常用方法如下:

  int addAndGet(int delta):以原子的方式将输入的数值与实例中的值相加,并返回结果

  boolean compareAndSet(int expect,int update):如果输入的数值等于预期值,则以原子方式将该值设置为输入的值

  int getAndIncrement():以原子方式将当前值加1,并返回自增前的值

  void lazySet(int newValue):最终设置为newValue,使用lazySet设置后,可能导致其他线程在一小段时间内还是可以读到旧的值

  int getAndSet(int newValue):以原子的方式设置为newValue的值,并返回旧值

  

  本篇博客开始的demo就是运用AtomicInteger的例子

复制代码
import java.util.concurrent.atomic.AtomicInteger;  public class AtomicIntegerTest {      static AtomicInteger ai = new AtomicInteger(1);      public 
                        
关键字:
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信