赞
踩
/** * @Description:演示AtomicInteger的基本用法,对比非原子类的线程安全问题,使用原子类之后,不需要加锁,也可以保证线程安全。 */ public class AtomicIntegerDemo1 implements Runnable{ private static final AtomicInteger atomicInteger = new AtomicInteger(); public void incrementAtomic(){ atomicInteger.getAndIncrement(); } //普通变量 private static volatile int basicCount =0; public void incrementBasic(){ basicCount++; } public static void main(String[] args) throws InterruptedException { AtomicIntegerDemo1 r = new AtomicIntegerDemo1(); Thread t1 = new Thread(r); Thread t2 = new Thread(r); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("原子类的结果是:"+atomicInteger.get()); //体现了普通变量在多线程情况下,无法保证线程安全 System.out.println("普通变量的结果是:"+basicCount); } @Override public void run(){ for (int i = 10000; i > 0; i--) { incrementAtomic(); incrementBasic(); } } }
从输出结果来看,普通变量无法保证线程安全。
在给普通变量的increment()加上synchronized也可以实现线程安全,但是效率较为低下。
public synchronized void incrementBasic(){
basicCount++;
}
/** * @Classname AtomicArrayDemo1 * @Description 演示原子数组的使用方法 * @Date 2021/2/16 9:09 * @Created by YoungLiu */ public class AtomicArrayDemo1 { public static void main(String[] args) throws InterruptedException { AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(1000); Increment increment = new Increment(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); threadsDecrementer[i].start(); threadsIncrementer[i]=new Thread(increment); threadsIncrementer[i].start(); } for (int i = 0; i < 100; i++) { threadsDecrementer[i].join(); threadsIncrementer[i].join(); } for(int i =0;i<atomicIntegerArray.length();i++){ if(atomicIntegerArray.get(i)!=0){ System.out.println("发现了非0值,错误的位置 "+i); } System.out.println(atomicIntegerArray.get(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 Increment implements Runnable{ private AtomicIntegerArray array; public Increment( AtomicIntegerArray array){ this.array=array; } @Override public void run() { for(int i=0;i<array.length();++i){ array.getAndIncrement(i); } } }
以spinLock的代码为示例
public class SpinLock { private AtomicReference<Thread> sign= new AtomicReference<>(); public void lock(){ //得到当前线程的引用 Thread current = Thread.currentThread(); while(!sign.compareAndSet(null,current)){ System.out.println(Thread.currentThread().getName()+"本次尝试获取自旋锁失败"); } } public void unlock(){ Thread current = Thread.currentThread(); 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 t0 = new Thread(runnable); Thread t1 = new Thread(runnable); t0.start(); t1.start(); } }
/** * @Classnam AtomicIntegerFieldUpdaterDemo * @Description:演示AtomicIntegerFieldUpdater用法 * @Date 2021/2/16 9:31 * @Created by YoungLiu */ public class AtomicIntegerFieldUpdaterDemo implements Runnable { static Candidate tom; static Candidate peter; public static AtomicIntegerFieldUpdater<Candidate> scoreUpdater = AtomicIntegerFieldUpdater.newUpdater(Candidate.class, "score"); @Override public void run() { for (int i = 0; i < 10000; i++) { peter.score++; //实现对普通变量的原子操作 scoreUpdater.getAndIncrement(tom); } } public static class Candidate { volatile int score; } public static void main(String[] args) throws InterruptedException { AtomicIntegerFieldUpdaterDemo r = new AtomicIntegerFieldUpdaterDemo(); tom = new Candidate(); peter = new Candidate(); Thread t1 = new Thread(r); Thread t2 = new Thread(r); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("upgrading tom:" + tom.score); System.out.println("normal peter:" + peter.score); } }
从程序输出结果可以看到,升级后的变量,实现了原子性操作。
1.可见范围 — 不能操作private的变量
2. 不支持static变量
/** * @Classname AtomicLongDemo * @Description 演示高并发场景下,LongAdder比AtomicLong性能高 * @Date 2021/2/16 10:09 * @Created by YoungLiu */ public class AtomicLongDemo { public static void main(String[] args) throws InterruptedException { AtomicLong counter = new AtomicLong(0); ExecutorService service = Executors.newFixedThreadPool(16); long start = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) { service.submit(new Task(counter)); } service.shutdown(); while(!service.isTerminated()){//为了计算执行任务的耗时; //此处等待所有任务执行完毕后才往下执行。 } long end = System.currentTimeMillis(); System.out.println(counter.get()); System.out.println("AtomicLong耗时:"+(end-start)); } private static class Task implements Runnable{ private AtomicLong counter; public Task(AtomicLong counter){ this.counter=counter; } @Override public void run() { for (int i = 0; i < 10000; i++) { counter.incrementAndGet(); } } } }
** * @Classname LongAdderDemo * @Description TODO * @Date 2021/2/16 10:15 * @Created by YoungLiu */ public class LongAdderDemo { public static void main(String[] args) throws InterruptedException { LongAdder counter = new LongAdder(); ExecutorService service = Executors.newFixedThreadPool(20); long start = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) { service.submit(new LongAdderDemo.Task(counter)); } service.shutdown(); while(!service.isTerminated()){ } long end = System.currentTimeMillis(); System.out.println(counter.sum()); System.out.println("longAdder耗时:"+(end-start)); } private static class Task implements Runnable{ private LongAdder counter; public Task(LongAdder counter){ this.counter=counter; } @Override public void run() { for (int i = 0; i < 10000; i++) { counter.increment(); } } } }
对比两个程序的输出,可以看出在高并发情况下,LongAdder的性能比AtomicLong要高。
由于CPU有不同的core,每个core做完一次操作后,其他的core都要刷新一次它的缓存,这会造成资源浪费。
/** * @Classname LongAccmulatorDemo * @Description 演示LongAccumulator用法 * @Date 2021/2/16 11:18 * @Created by YoungLiu */ public class LongAccmulatorDemo { public static void main(String[] args) { //最开始这个0,是赋给x的 LongAccumulator accumulator = new LongAccumulator((x, y) -> x + y, 0); ExecutorService service = Executors.newFixedThreadPool(8); IntStream.range(1,10).forEach(i-> service.submit(()->accumulator.accumulate(i))); accumulator.accumulate(1); service.shutdown(); while(!service.isTerminated()){ } System.out.println(accumulator.getThenReset()); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。