原子类
1. LongAdder
2. LongAccumulator
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| { LongAdder longAdder = new LongAdder();
longAdder.increment(); longAdder.increment(); longAdder.increment(); System.out.println(longAdder.sum());
LongAccumulator longAccumulator = new LongAccumulator(new LongBinaryOperator() { @Override public long applyAsLong(long left, long right) { return left + right; } },0);
longAccumulator.accumulate(1); longAccumulator.accumulate(3); System.out.println(longAccumulator.get()); }
|
运行结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| class ClickNumber { int number = 0; public synchronized void clickBySynchronized() { number++; }
AtomicLong atomicLong = new AtomicLong(0); public void clickByAtomicLong() { atomicLong.getAndIncrement(); }
LongAdder longAdder = new LongAdder(); public void clickByLongAdder() { longAdder.increment(); }
LongAccumulator longAccumulator = new LongAccumulator((x,y) -> x + y,0); public void clickByLongAccumulator() { longAccumulator.accumulate(1); }
}
public class AccumulatorCompareDemo { public static final int _1W = 10000; public static final int threadNumber = 50;
public static void main(String[] args) throws InterruptedException { ClickNumber clickNumber = new ClickNumber(); long startTime; long endTime;
CountDownLatch countDownLatch1 = new CountDownLatch(threadNumber); CountDownLatch countDownLatch2 = new CountDownLatch(threadNumber); CountDownLatch countDownLatch3 = new CountDownLatch(threadNumber); CountDownLatch countDownLatch4 = new CountDownLatch(threadNumber);
startTime = System.currentTimeMillis(); for (int i = 1; i <=threadNumber; i++) { new Thread(() -> { try { for (int j = 1; j <=100 * _1W; j++) { clickNumber.clickBySynchronized(); } } finally { countDownLatch1.countDown(); } },String.valueOf(i)).start(); } countDownLatch1.await(); endTime = System.currentTimeMillis(); System.out.println("----costTime: "+(endTime - startTime) +" 毫秒"+"\t clickBySynchronized: "+clickNumber.number);
startTime = System.currentTimeMillis(); for (int i = 1; i <=threadNumber; i++) { new Thread(() -> { try { for (int j = 1; j <=100 * _1W; j++) { clickNumber.clickByAtomicLong(); } } finally { countDownLatch2.countDown(); } },String.valueOf(i)).start(); } countDownLatch2.await(); endTime = System.currentTimeMillis(); System.out.println("----costTime: "+(endTime - startTime) +" 毫秒"+"\t clickByAtomicLong: "+clickNumber.atomicLong.get());
startTime = System.currentTimeMillis(); for (int i = 1; i <=threadNumber; i++) { new Thread(() -> { try { for (int j = 1; j <=100 * _1W; j++) { clickNumber.clickByLongAdder(); } } finally { countDownLatch3.countDown(); } },String.valueOf(i)).start(); } countDownLatch3.await(); endTime = System.currentTimeMillis(); System.out.println("----costTime: "+(endTime - startTime) +" 毫秒"+"\t clickByLongAdder: "+clickNumber.longAdder.sum());
startTime = System.currentTimeMillis(); for (int i = 1; i <=threadNumber; i++) { new Thread(() -> { try { for (int j = 1; j <=100 * _1W; j++) { clickNumber.clickByLongAccumulator(); } } finally { countDownLatch4.countDown(); } },String.valueOf(i)).start(); } countDownLatch4.await(); endTime = System.currentTimeMillis(); System.out.println("----costTime: "+(endTime - startTime) +" 毫秒"+"\t clickByLongAccumulator: "+clickNumber.longAccumulator.get());
} }
|
运行结果
—-costTime: 5057 毫秒 clickBySynchronized: 50000000
—-costTime: 823 毫秒 clickByAtomicLong: 50000000
—-costTime: 129 毫秒 clickByLongAdder: 50000000
—-costTime: 102 毫秒 clickByLongAccumulator: 50000000
3. AtomicLong
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
| class ClickNumber { int number = 0; public synchronized void clickBySynchronized() { number++; }
AtomicLong atomicLong = new AtomicLong(0); public void clickByAtomicLong() { atomicLong.getAndIncrement(); }
LongAdder longAdder = new LongAdder(); public void clickByLongAdder() { longAdder.increment(); }
LongAccumulator longAccumulator = new LongAccumulator((x,y) -> x + y,0); public void clickByLongAccumulator() { longAccumulator.accumulate(1); }
}
public class AccumulatorCompareDemo { public static final int _1W = 10000; public static final int threadNumber = 50;
public static void main(String[] args) throws InterruptedException { ClickNumber clickNumber = new ClickNumber(); long startTime; long endTime;
CountDownLatch countDownLatch1 = new CountDownLatch(threadNumber); CountDownLatch countDownLatch2 = new CountDownLatch(threadNumber); CountDownLatch countDownLatch3 = new CountDownLatch(threadNumber); CountDownLatch countDownLatch4 = new CountDownLatch(threadNumber);
startTime = System.currentTimeMillis(); for (int i = 1; i <=threadNumber; i++) { new Thread(() -> { try { for (int j = 1; j <=100 * _1W; j++) { clickNumber.clickBySynchronized(); } } finally { countDownLatch1.countDown(); } },String.valueOf(i)).start(); } countDownLatch1.await(); endTime = System.currentTimeMillis(); System.out.println("----costTime: "+(endTime - startTime) +" 毫秒"+"\t clickBySynchronized: "+clickNumber.number);
startTime = System.currentTimeMillis(); for (int i = 1; i <=threadNumber; i++) { new Thread(() -> { try { for (int j = 1; j <=100 * _1W; j++) { clickNumber.clickByAtomicLong(); } } finally { countDownLatch2.countDown(); } },String.valueOf(i)).start(); } countDownLatch2.await(); endTime = System.currentTimeMillis(); System.out.println("----costTime: "+(endTime - startTime) +" 毫秒"+"\t clickByAtomicLong: "+clickNumber.atomicLong.get());
startTime = System.currentTimeMillis(); for (int i = 1; i <=threadNumber; i++) { new Thread(() -> { try { for (int j = 1; j <=100 * _1W; j++) { clickNumber.clickByLongAdder(); } } finally { countDownLatch3.countDown(); } },String.valueOf(i)).start(); } countDownLatch3.await(); endTime = System.currentTimeMillis(); System.out.println("----costTime: "+(endTime - startTime) +" 毫秒"+"\t clickByLongAdder: "+clickNumber.longAdder.sum());
startTime = System.currentTimeMillis(); for (int i = 1; i <=threadNumber; i++) { new Thread(() -> { try { for (int j = 1; j <=100 * _1W; j++) { clickNumber.clickByLongAccumulator(); } } finally { countDownLatch4.countDown(); } },String.valueOf(i)).start(); } countDownLatch4.await(); endTime = System.currentTimeMillis(); System.out.println("----costTime: "+(endTime - startTime) +" 毫秒"+"\t clickByLongAccumulator: "+clickNumber.longAccumulator.get());
} }
|
运行结果
—-costTime: 4763 毫秒 clickBySynchronized: 50000000
—-costTime: 807 毫秒 clickByAtomicLong: 50000000
—-costTime: 111 毫秒 clickByLongAdder: 50000000
—-costTime: 90 毫秒 clickByLongAccumulator: 50000000
4. AtomicInteger
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| class MyNumber { AtomicInteger atomicInteger = new AtomicInteger();
public void addPlusPlus() { atomicInteger.getAndIncrement(); } }
public class AtomicIntegerDemo { public static final int SIZE = 50;
public static void main(String[] args) throws InterruptedException { MyNumber myNumber = new MyNumber(); CountDownLatch countDownLatch = new CountDownLatch(SIZE);
for (int i = 1; i <=SIZE; i++) { new Thread(() -> { try { for (int j = 1; j <=1000; j++) { myNumber.addPlusPlus(); } } finally { countDownLatch.countDown(); } },String.valueOf(i)).start(); } countDownLatch.await();
System.out.println(Thread.currentThread().getName()+"\t"+"result: "+myNumber.atomicInteger.get()); } }
|
运行结果
5. AtomicIntegerArray
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| { AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(new int[5]);
for (int i = 0; i <atomicIntegerArray.length(); i++) { System.out.println(atomicIntegerArray.get(i)); } System.out.println();
int tmpInt = 0;
tmpInt = atomicIntegerArray.getAndSet(0,1122); System.out.println(tmpInt+"\t"+atomicIntegerArray.get(0));
tmpInt = atomicIntegerArray.getAndIncrement(0); System.out.println(tmpInt+"\t"+atomicIntegerArray.get(0)); }
|
运行结果
6. AtomicIntegerFieldUpdater
原理:原子性地更新对象的volatile字段,无需使用重量级的锁机制,它通过基于反射的API实现了细粒度的并发控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| class BankAccount { String bankName = "CCB";
public volatile int money = 0;
public void add() { money++; }
AtomicIntegerFieldUpdater<BankAccount> fieldUpdater = AtomicIntegerFieldUpdater.newUpdater(BankAccount.class,"money");
public void transMoney(BankAccount bankAccount) { fieldUpdater.getAndIncrement(bankAccount); }
}
public class AtomicIntegerFieldUpdaterDemo { public static void main(String[] args) throws InterruptedException { BankAccount bankAccount = new BankAccount(); CountDownLatch countDownLatch = new CountDownLatch(10);
for (int i = 1; i <=10; i++) { new Thread(() -> { try { for (int j = 1; j <=1000; j++) { bankAccount.transMoney(bankAccount); } } finally { countDownLatch.countDown(); } },String.valueOf(i)).start(); }
countDownLatch.await();
System.out.println(Thread.currentThread().getName()+"\t"+"result: "+bankAccount.money); } }
|
运行结果
7. AtomicMarkableReference
解决ABA问题,如果变量已经被更新,则isMarked
返回true
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| static AtomicMarkableReference markableReference = new AtomicMarkableReference(100,false); { new Thread(() -> { boolean marked = markableReference.isMarked(); System.out.println(Thread.currentThread().getName()+"\t"+"默认标识:"+marked); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } boolean a = markableReference.compareAndSet(100,1000,marked,!marked); System.out.println(Thread.currentThread().getName()+"\t"+"t1线程CASresult: "+a); System.out.println(Thread.currentThread().getName()+"\t"+markableReference.isMarked()); System.out.println(Thread.currentThread().getName()+"\t"+markableReference.getReference()); },"t1").start();
new Thread(() -> { boolean marked = markableReference.isMarked(); System.out.println(Thread.currentThread().getName()+"\t"+"默认标识:"+marked);
try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } boolean b = markableReference.compareAndSet(100, 2000, marked, !marked); System.out.println(Thread.currentThread().getName()+"\t"+"t2线程CASresult: "+b); System.out.println(Thread.currentThread().getName()+"\t"+markableReference.isMarked()); System.out.println(Thread.currentThread().getName()+"\t"+markableReference.getReference()); },"t2").start(); }
|
运行结果
t1 默认标识:false
t2 默认标识:false
t1 t1线程CASresult: true
t1 true
t1 1000
t2 t2线程CASresult: false
t2 true
t2 1000
8. AtomicStampedReference
和AtomicMarkableReference
一样,解决ABA问题,这里使用的是version版本号来区分数据是否发生了改变
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| @NoArgsConstructor @AllArgsConstructor @Data class Book { private int id; private String bookName; }
public class AtomicStampedDemo { public static void main(String[] args) { Book javaBook = new Book(1,"javaBook");
AtomicStampedReference<Book> stampedReference = new AtomicStampedReference<>(javaBook,1);
System.out.println(stampedReference.getReference()+"\t"+stampedReference.getStamp());
Book mysqlBook = new Book(2,"mysqlBook");
boolean b; b = stampedReference.compareAndSet(javaBook, mysqlBook, stampedReference.getStamp(), stampedReference.getStamp() + 1);
System.out.println(b+"\t"+stampedReference.getReference()+"\t"+stampedReference.getStamp());
b = stampedReference.compareAndSet(mysqlBook, javaBook, stampedReference.getStamp(), stampedReference.getStamp() + 1);
System.out.println(b+"\t"+stampedReference.getReference()+"\t"+stampedReference.getStamp());
} }
|
运行结果
Book(id=1, bookName=javaBook) 1
true Book(id=2, bookName=mysqlBook) 2
true Book(id=1, bookName=javaBook) 3
9. AtomicReferenceFieldUpdater
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| class MyVar { public volatile Boolean isInit = Boolean.FALSE;
AtomicReferenceFieldUpdater<MyVar,Boolean> referenceFieldUpdater = AtomicReferenceFieldUpdater.newUpdater(MyVar.class,Boolean.class,"isInit");
public void init(MyVar myVar) { if (referenceFieldUpdater.compareAndSet(myVar,Boolean.FALSE,Boolean.TRUE)) { System.out.println(Thread.currentThread().getName()+"\t"+"----- start init,need 2 seconds"); try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"\t"+"----- over init"); } else { System.out.println(Thread.currentThread().getName()+"\t"+"----- 已经有线程在进行初始化工作。。。。。"); } } }
public class AtomicReferenceFieldUpdaterDemo { public static void main(String[] args) { MyVar myVar = new MyVar();
for (int i = 1; i <=5; i++) { new Thread(() -> { myVar.init(myVar); },String.valueOf(i)).start(); } } }
|
运行结果
2 —– 已经有线程在进行初始化工作。。。。。
1 —– start init,need 2 seconds
3 —– 已经有线程在进行初始化工作。。。。。
4 —– 已经有线程在进行初始化工作。。。。。
5 —– 已经有线程在进行初始化工作。。。。。
1 —– over init