package com.gzs.learn.juc.base;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

import org.junit.Test;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
 * 原子操作示例
 *
 * @author guanzhisong
 * @date 2017年11月4日
 */
@Slf4j
public class AtomicExample {
    @Test
    public void testAtomic() throws InterruptedException {
        Counter counter = new Counter();
        // 线程数
        int threadCount = 100;
        // 可以先不用理会这两个类,此处用途是确保线程创建完毕以后能够以一个相对一致的时间点同时执行线程代码
        CountDownLatch startLatch = new CountDownLatch(1);
        CountDownLatch waitLatch = new CountDownLatch(threadCount);
        // 创建线程
        for (int i = 0; i < threadCount; i++) {
            new ExampleThread(counter, startLatch, waitLatch).start();
        }
        // 开始执行累加
        startLatch.countDown();
        // 等待线程执行完毕
        waitLatch.await();
        log.info("not thread safe counter:{}", counter.getCount());
        log.info("thread safe counter:{}", counter.getSyncCount());
        log.info("atomic counter:{}", counter.getAtomicCounter().get());
    }
}


@Data
class Counter {
    private int count;
    private int syncCount;
    private AtomicInteger atomicCounter;

    public Counter() {
        count = 0;
        syncCount = 0;
        atomicCounter = new AtomicInteger(0);
    }

    public void notSafeCount() {
        count++;
    }

    public synchronized void safeCount() {
        syncCount++;
    }

    public void atomicCount() {
        atomicCounter.incrementAndGet();
    }
}


@AllArgsConstructor
class ExampleThread extends Thread {
    private static final int LOOP_TIMES = 100;
    private Counter counter;
    private CountDownLatch startLatch;
    private CountDownLatch waitLatch;

    @Override
    public void run() {
        try {
            // 线程默认是阻塞在此处的,主线程调用startLatch.countDown()即解除阻塞状态
            startLatch.await();
            for (int i = 0; i < LOOP_TIMES; i++) {
                counter.notSafeCount();
                counter.safeCount();
                counter.atomicCount();
            }
        } catch (InterruptedException e) {
        } finally {
            waitLatch.countDown();
        }
    }
}

@@ -1129,24 +1129,1204 @@
 et());%0A    %7D
+%0A%0A    @Test%0A    public void testLongAtomic() throws InterruptedException %7B%0A        // %E8%8E%B7%E5%8F%96%E5%B9%B6%E6%89%93%E5%8D%B0%E5%BD%93%E5%89%8DJVM%E6%98%AF32%E4%BD%8D%E8%BF%98%E6%98%AF64%E4%BD%8D%E7%9A%84%0A        String arch = System.getProperty(%22sun.arch.data.model%22);%0A        System.out.println(arch + %22-bit%22);%0A        LongAtomTest t1 = new LongAtomTest(1);%0A        LongAtomTest t2 = new LongAtomTest(-1);%0A        Thread T1 = new Thread(t1);%0A        Thread T2 = new Thread(t2);%0A        T1.start();%0A        T2.start();%0A        T1.join();%0A        T2.join();%0A    %7D%0A%7D%0A%0A%0Aclass LongAtomTest implements Runnable %7B%0A    private static long field = 0;%0A%0A    private volatile long value;%0A%0A    public long getValue() %7B%0A        return value;%0A    %7D%0A%0A    public void setValue(long value) %7B%0A        this.value = value;%0A    %7D%0A%0A    public LongAtomTest(long value) %7B%0A        this.setValue(value);%0A    %7D%0A%0A    @Override%0A    public void run() %7B%0A        int i = 0;%0A        while (i %3C 100000) %7B%0A            LongAtomTest.field = this.getValue();%0A            i++;%0A            long temp = LongAtomTest.field;%0A            if (temp != 1L && temp != -1L) %7B%0A                System.out.println(%22%E5%87%BA%E7%8E%B0%E9%94%99%E8%AF%AF%E7%BB%93%E6%9E%9C%22 + temp);%0A                System.exit(0);%0A            %7D%0A        %7D%0A        System.out.println(%22%E8%BF%90%E8%A1%8C%E6%AD%A3%E7%A1%AE%22);%0A    %7D
 %0A%7D%0A%0A%0A@Data%0Ac

add example