类型 | 具体类型 |
---|---|
Atomic* 基本类型原子类 | AtomicInteger、AtomicLong、AtomicBoolean |
Atomic*Array 数组类型原子类 | AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray |
Atomic*Reference 引用类型原子类 | AtomicReference、AtomicStampedReference、AtomicMarkableReference |
Atomic*FieldUpdater 升级类型原子类 | AtomicIntegerfieldupdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater |
Adder 累加器 | LongAdder、DoubleAdder |
Accumulator 积累器 | LongAccumulator、DoubleAccumulator |
方法 | 作用 |
---|---|
public final int get() | 获取当前的值 |
public final int getAndSet(int newValue) | 获取当前的值,并设置新的值 |
public final int getAndIncrement() | 获取当前的值,并自增+1 |
public final int getAndDecrement() | 获取当前的值,并自减-1 |
public final int getAndAdd(int delta) | 获取当前的值,并加上预期的值。getAndIncrement和getAndDecrement不满足,可使用当前方法 |
boolean compareAndSet(int expect, int update) | 如果输入的数值等于预期值,则以原子方式将该值更新为输入值(update) |
/** * 堆代码 duidaima.com * 演示AtomicInteger的基本用法,并对比非原子类的线程安全问题 */ publicclass AtomicIntegerDemo1 implements Runnable { privatestaticfinal AtomicInteger atomicInteger = new AtomicInteger(); privatestaticfinal AtomicInteger atomicInteger2 = new AtomicInteger(); //原子类型自增 public void atomicIncrement(){ atomicInteger.getAndIncrement(); } //原子类型 getAndAdd() public void atomicAdd(){ atomicInteger2.getAndAdd(4); } privatestaticvolatileint basicCount = 0; //普通类型自增 public void basicIncrement(){ basicCount++; } @Override public void run() { for (int i = 0; i < 10000; i++) { atomicIncrement(); basicIncrement(); atomicAdd(); } } //主函数 public static void main(String[] args) throws InterruptedException { AtomicIntegerDemo1 aid = new AtomicIntegerDemo1(); Thread thread1 = new Thread(aid); Thread thread2 = new Thread(aid); thread1.start(); thread2.start(); thread1.join(); thread2.join(); System.out.println("原子类的结果:"+atomicInteger.get()); System.out.println("普通变量值:"+basicCount); System.out.println("getAndAdd的结果:"+atomicInteger2.get()); } }
//普通类型自增 public synchronized void basicIncrement(){ basicCount++; }
/** * 演示原子数组的使用方法 */ publicclass AtomicArray { public static void main(String[] args) { AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(1000); Incrementer incrementer = new Incrementer(atomicIntegerArray); Decrementer decrementer = new Decrementer(atomicIntegerArray); Thread[] threadsIncrementer = new Thread[100]; Thread[] threadsDecrementer = new Thread[100]; for (int i = 0; i < 100; i++) { threadsDecrementer[i] = new Thread(decrementer); threadsIncrementer[i] = new Thread(incrementer); threadsDecrementer[i].start(); threadsIncrementer[i].start(); } // Thread.sleep(10000); for (int i = 0; i < 100; i++) { try { threadsDecrementer[i].join(); threadsIncrementer[i].join(); } catch (InterruptedException e) { e.printStackTrace(); } } for (int i = 0; i <atomicIntegerArray.length() ; i++) { if (atomicIntegerArray.get(i)!=0){ System.out.println("发现了错误: " +i); } } System.out.println("运行结束"); } } //自减任务类 class Decrementer implements Runnable{ private AtomicIntegerArray array; public Decrementer(AtomicIntegerArray array) { this.array = array; } @Override public void run() { for (int i = 0; i < array.length(); i++) { array.getAndDecrement(i); } } } //自增任务类 class Incrementer implements Runnable{ private AtomicIntegerArray array; public Incrementer(AtomicIntegerArray array) { this.array = array; } @Override public void run() { for (int i = 0; i < array.length(); i++) { array.getAndIncrement(i); } } }
/** * 自旋锁演示 */ publicclass SpinLock { private AtomicReference<Thread> sign = new AtomicReference<>(); //加锁操作 public void lock(){ Thread current = Thread.currentThread(); //期待是null,如果是期望的,就将其设置为current while (!sign.compareAndSet(null,current)){ System.out.println(Thread.currentThread().getName()+":自旋获取失败,再次尝试"); } } //解锁操作 public void unlock(){ Thread current = Thread.currentThread(); //期待加锁的当前线程,如果是期望的,就将其设置为为null,也就是没有持有了,就是解锁了 sign.compareAndSet(current,null); } public static void main(String[] args) { SpinLock spinLock = new SpinLock(); Runnable runnable = new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + ":开始尝试获取自旋锁"); spinLock.lock(); System.out.println(Thread.currentThread().getName() + ":获取到了自旋锁"); try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } finally { spinLock.unlock(); System.out.println(Thread.currentThread().getName() + ":释放了自旋锁"); } } }; Thread thread1 = new Thread(runnable); Thread thread2 = new Thread(runnable); thread1.start(); thread2.start(); } }
/** * 堆代码 duidaima.com * 演示AtomicIntegerFieildUpdater的用法 */ publicclass AtomicIntegerFieildUpdater implements Runnable { static Candidate tom; static Candidate jack; //newUpdater():参数1指定哪个类,参数2哪个字段。这里的入参和反射的入参很像,因为它的底层原理是反射 publicstatic AtomicIntegerFieldUpdater<Candidate> scoreUpdater = AtomicIntegerFieldUpdater.newUpdater(Candidate.class,"score"); @Override public void run() { for (int i = 0; i < 10000; i++) { tom.score++;//普通自增 scoreUpdater.getAndIncrement(jack);//通过包装自增 } } //候选人类 publicstaticclass Candidate{ //分数 volatileint score; } //主函数 public static void main(String[] args) throws InterruptedException { tom = new Candidate(); jack = new Candidate(); AtomicIntegerFieildUpdater a = new AtomicIntegerFieildUpdater(); Thread thread1 = new Thread(a); Thread thread2 = new Thread(a); thread1.start(); thread2.start(); thread1.join(); thread2.join(); System.out.println("普通自增: "+tom.score); // 获取值时还按照普通变量操作 System.out.println("升级自增: "+jack.score); } }
.可见范围,由public修饰的变量,private不行
(1)AtomicLong,20个线程并发,每个线程执行10000次 publicclass AtomicLongDemo { //主函数 public static void main(String[] args) throws InterruptedException { AtomicLong counter = new AtomicLong(0); //新建线程池 ExecutorService pool = Executors.newFixedThreadPool(20); long startTime = System.currentTimeMillis(); //任务次数 for (int i = 0; i < 10000; i++) { pool.submit(new Task(counter)); } //关闭线程池 pool.shutdown(); while (!pool.isTerminated()){ } long endTime = System.currentTimeMillis(); System.out.println(counter.get()); System.out.println("AtomicLong完成时间:"+(endTime-startTime)+"毫秒"); } //任务内部类 publicstaticclass Task implements Runnable{ private AtomicLong count; public Task(AtomicLong count) { this.count = count; } @Override public void run() { for (int i = 0; i < 10000; i++) { count.incrementAndGet();//自增 } } } }
publicclass LongAdderDemo { //主函数 public static void main(String[] args) throws InterruptedException { LongAdder counter = new LongAdder(); //新建线程池 ExecutorService pool = Executors.newFixedThreadPool(20); long startTime = System.currentTimeMillis(); //任务次数 for (int i = 0; i < 10000; i++) { pool.submit(new Task(counter)); } //关闭线程池 pool.shutdown(); while (!pool.isTerminated()){ } long endTime = System.currentTimeMillis(); System.out.println(counter.sum()); System.out.println("LongAdder完成时间:"+(endTime-startTime)+"毫秒"); } //任务内部类 publicstaticclass Task implements Runnable{ private LongAdder count; public Task(LongAdder count) { this.count = count; } @Override public void run() { for (int i = 0; i < 10000; i++) { count.increment();//自增 } } } }
LongAdder中,每个线程他自己有独立的计数器,只有在执行 sum()方法时才会将各个线程德计数器汇总
/** * Returns the current sum. The returned value is <em>NOT</em> an * atomic snapshot; invocation in the absence of concurrent * updates returns an accurate result, but concurrent updates that * occur while the sum is being calculated might not be * incorporated. * * @return the sum */ public long sum() { Cell[] as = cells; Cell a; long sum = base; if (as != null) { for (int i = 0; i < as.length; ++i) { if ((a = as[i]) != null) sum += a.value; } } return sum; }上面源码中会判断,如果as变量不为null 也就是cell[]数组中有值,就会对Cell[] 和base一起相加后返回最后的结果。
publicclass LongAccumulatorDemo { public static void main(String[] args) { //参数1:表达式 //参数2:初始值,对X的第一次定义 //最开始会将初始值赋给X ,y就是之前的结果;类似于 数学归纳法 LongAccumulator accumulator = new LongAccumulator((x, y) -> x + y, 100); // 这里的 100 就是初始值 accumulator.accumulate(1);//此时,x=1,y=100,结果为101 accumulator.accumulate(2);//此时,x=2,y=101,结果为103 System.out.println(accumulator.getThenReset()); } }
publicclass LongAccumulatorDemo { public static void main(String[] args) { //求1加到9中最大的数 LongAccumulator accumulator = new LongAccumulator((x, y) -> Math.max(x,y), 0); ExecutorService pool = Executors.newFixedThreadPool(10); //从1加到9 IntStream.range(1,10).forEach(i->pool.submit(()->accumulator.accumulate(i))); pool.shutdown(); while (!pool.isTerminated()){ } System.out.println(accumulator.getThenReset()); } }