开发时的一个小问题:如何在for-each定位到循环次数,常规的写法是定义一个i=1,循环中i++来实现,但是会出现线程不安全的风险,请教了对面大佬后发现AtomicInteger正好能满足确定循环次数和线程安全的条件,而且也适用while循环~
目录
一、AtomicInteger介绍
AtomicInteger是一个提供原子操作的Integer类,通过线程安全的方式操作加减,适合高并发情况下的使用。
1、创建AtomicInteger 设置值获取值
需要注意的是,AtomicInteger 和 Integer/int 一样都是一个数值,不过AtomicInteger 具备更多的功能。
//初始值是 0,int也可用Integer替代
AtomicInteger atomicInteger1 = new AtomicInteger();
int currentValue1 = atomicInteger1.get(); //0
//初始值是 100
AtomicInteger atomicInteger2 = new AtomicInteger(100);
int currentValue2 = atomicInteger2.get(); //100
//设值1234,挤掉100
atomicInteger2.set(1234);
int currentValue3 = atomicInteger2.get(); //1234
2、作为原子计数器
AtomicIntegerclass提供了一些以原子方式执行加法和减法操作的方法,也是用于确定循环次数的主要办法。
addAndGet()- 以原子方式将给定值添加到当前值,并在添加后返回新值。
getAndAdd() - 以原子方式将给定值添加到当前值并返回旧值。
incrementAndGet()- 以原子方式将当前值递增1并在递增后返回新值。它相当于i ++操作。
getAndIncrement() - 以原子方式递增当前值并返回旧值。它相当于++ i操作。
decrementAndGet()- 原子地将当前值减1并在减量后返回新值。它等同于i-操作。
getAndDecrement() - 以原子方式递减当前值并返回旧值。它相当于-i操作。
3、比较和交换操作
比较和交换操作将内存位置的内容与给定值进行比较,并且只有它们相同时,才将该内存位置的内容修改为给定的新值,这是作为单个原子操作完成的。
//1、默认初始值:100
AtomicInteger atomicInteger = new AtomicInteger(100);
//2、此时当前值是100,给定值是100,更新值是110,更改成功后当前值为110
boolean isSuccess = atomicInteger.compareAndSet(100,110);
System.out.println(isSuccess); //true
//3、此时当前值是110,给定值是100,更改失败,当前值依然为100
boolean isSuccess = atomicInteger.compareAndSet(100,120);
System.out.println(isSuccess); //false
二、AtomicInteger确定循环次数
1、常见的循环次数确定
可见i++的方式是比较方便的,尤其适用于集合内元素数量不确定的情况。
public static void main(String[] args) {
//定义一个String类型的集合
List<String> list = new ArrayList<>();
list.add("11");
list.add("22");
list.add("33");
//for循环通过i++
int i = 0;
for(String m : list){
i++;
}
System.out.println(i); //循环次数:3
//forEach循环通过i++
int i = 0;
list.forEach(string -> {
i++;
});
System.out.println(i); //循环次数:3
}
2、AtomicInteger确定循环次数
如下代码所示,如果不确定循环到底会进行多少次,完全可以使用AtomicInteger的计数器功能,线程安全放心使用,下边只是列出了forEach的情况,while循环也是可以使用AtomicInteger的,大家有兴趣的话可以试一下哈~
public static void main(String[] args) {
//定义一个String类型的集合
List<String> list = new ArrayList<>();
list.add("11");
list.add("22");
list.add("33");
//使用AtomicInteger里的getAndAdd
AtomicInteger i = new AtomicInteger(0); //定义初始值为0,默认也为0
list.forEach(Integer -> {
i.getAndAdd(1); //incrementAndGet()方法也可
});
System.out.println(i); //循环次数:3
}
总结
大家如果有疑问都可以评论提出,有不足之处请大家批评指正,希望能多结识这方面的朋友,共同学习、共同进步,参考文章:https://www.jianshu.com/p/073096a729f6