原子操作类 ——AtomicLong
public class AtomicLongTest {
private static Random random = new Random(2);
//定义一个Long类型的原子计数器
private static AtomicLong count = new AtomicLong();
public static void main(String[] args) throws Exception {
//(1)获取两组随机数,每组20个
List<Integer> list1 = new ArrayList<>(20);
List<Integer> list2 = new ArrayList<>(20);
//(2)获取时记录可以被3除余数为0的数的的个数
long j = 0;
for (int i = 0; i < 20; i++) {
int a = random.nextInt(50);
System.out.print(a + " ");
list1.add(a);
if (a % 3 == 0) {
j ++;
}
int b = random.nextInt(50);
System.out.print(b + " ");
list2.add(b);
if (b % 3 == 0) {
j ++;
}
}
//(3)开启一个线程计算出list1中可以被3除,余数为0的数的个数,进行count.getAndIncrement()操作
Thread thread1 = new Thread(() -> {
for (Integer a : list1) {
if (a % 3 == 0) {
count.getAndIncrement();
}
}
});
//(4)再开启一个线程计算出list2中可以被3除,余数为0的数的个数,进行count.getAndIncrement()操作
Thread thread2 = new Thread(() -> {
for (Integer a : list2) {
if (a % 3 == 0) {
count.getAndIncrement();
}
}
});
//启动thread1和thread2
thread1.start();
thread2.start();
//等待thread1和thread2执行完
thread1.join();
thread2.join();
System.out.println();
System.out.println("j = " + j);
System.out.println("count = " + count);
}
}
输出结果为
8 22 40 17 39 0 6 19 47 18 44 36 34 14 14 16 17 49 30 31 28 47 49 42 6 14 12 35 3 12 29 26 7 0 30 24 47 15 17 38
j = 15
count = 15
在多线程的情况下,count的值喝j的值始终保持相等;因为在AtomicLong中都是用了CAS非阻塞算法;
- final long getAndIncrement()
public final long getAndIncrement() {
return unsafe.getAndAddLong(this, valueOffset, 1L);
}
- final long getAndAddLong(Object var1, long var2, long var4)
public final long getAndAddLong(Object var1, long var2, long var4) {
long var6;
do {
var6 = this.getLongVolatile(var1, var2);
} while(!this.compareAndSwapLong(var1, var2, var6, var6 + var4));
return var6;
}
这里虽然使用了CAS非阻塞算法,性能方面比使用Synchronized关键字,获取其他锁机制要高很多,但是还有更急优秀的方式,后续再说;