Java AtomicInteger類(lèi)使用方法實(shí)例講解
1、java.util.concurrent.atomic 的包里有AtomicBoolean, AtomicInteger,AtomicLong,AtomicLongArray,AtomicReference等原子類(lèi)的類(lèi),主要用于在高并發(fā)環(huán)境下的高效程序處理,來(lái)幫助我們簡(jiǎn)化同步處理.
在Java語(yǔ)言中,++i和i++操作并不是線程安全的,在使用的時(shí)候,不可避免的會(huì)用到synchronized關(guān)鍵字。而AtomicInteger則通過(guò)一種線程安全的加減操作接口。
2、AtomicInteger的基本方法
創(chuàng)建一個(gè)AtomicInteger
System.out.println(atomicInteger.get());
--->輸出 : 123
創(chuàng)建一個(gè)不傳值的,默認(rèn)值為0
AtomicInteger atomicInteger = new AtomicInteger();System.out.println(atomicInteger.get());---->輸出: 0
獲取和賦值
atomicInteger.get(); //獲取當(dāng)前值atomicInteger.set(999); //設(shè)置當(dāng)前值
atomicInteger.compareAndSet(expectedValue,newValue)
public static void main(String[] args) { AtomicInteger atomicInteger = new AtomicInteger(0); System.out.println(atomicInteger.get()); int expectedValue = 123; int newValue = 234; Boolean b =atomicInteger.compareAndSet(expectedValue, newValue); System.out.println(b); System.out.println(atomicInteger); }----》輸出結(jié)果為: 0 false 0 public static void main(String[] args) { AtomicInteger atomicInteger = new AtomicInteger(123); System.out.println(atomicInteger.get()); int expectedValue = 123; int newValue = 234; Boolean b =atomicInteger.compareAndSet(expectedValue, newValue); System.out.println(b); System.out.println(atomicInteger); }-----》輸出結(jié)果為: 123 true 234
由上可知該方法表示,atomicInteger的值與expectedValue相比較,如果不相等,則返回false,atomicInteger原有值保持不變;如果兩者相等,則返回true,atomicInteger的值更新為newValue
getAndAdd()方法與AddAndGet方法
AtomicInteger atomicInteger = new AtomicInteger(123); System.out.println(atomicInteger.get()); --123 System.out.println(atomicInteger.getAndAdd(10)); --123 獲取當(dāng)前值,并加10 System.out.println(atomicInteger.get()); --133 System.out.println(atomicInteger.addAndGet(10)); --143 獲取加10后的值,先加10 System.out.println(atomicInteger.get()); --143
getAndDecrement()和DecrementAndGet()方法
AtomicInteger atomicInteger = new AtomicInteger(123); System.out.println(atomicInteger.get()); --123 System.out.println(atomicInteger.getAndDecrement()); --123 獲取當(dāng)前值并自減 System.out.println(atomicInteger.get()); --122 System.out.println(atomicInteger.decrementAndGet()); --121 先自減再獲取減1后的值 System.out.println(atomicInteger.get()); --121
3、使用AtomicInteger,即使不用同步塊synchronized,最后的結(jié)果也是100,可用看出AtomicInteger的作用,用原子方式更新的int值。主要用于在高并發(fā)環(huán)境下的高效程序處理。使用非阻塞算法來(lái)實(shí)現(xiàn)并發(fā)控制。
public class Counter { public static AtomicInteger count = new AtomicInteger(0); public static void inc(){ try{ Thread.sleep(1); //延遲1毫秒 }catch (InterruptedException e){ //catch住中斷異常,防止程序中斷 e.printStackTrace(); } count.getAndIncrement();//count值自加1 } public static void main(String[] args) throws InterruptedException { final CountDownLatch latch = new CountDownLatch(100); for(int i=0;i<100;i++){ new Thread(new Runnable() {@Overridepublic void run() { Counter.inc(); latch.countDown();} }).start(); } latch.await(); System.out.println('運(yùn)行結(jié)果:'+Counter.count); }}
運(yùn)行結(jié)果: 100
4、使用普通Integer
public class Counter { public volatile static int count = 0; public static void inc(){ try{ Thread.sleep(1); //延遲1毫秒 }catch (InterruptedException e){ //catch住中斷異常,防止程序中斷 e.printStackTrace(); } count++;//count值自加1 } public static void main(String[] args) throws InterruptedException { final CountDownLatch latch = new CountDownLatch(100); for(int i=0;i<100;i++){ new Thread(new Runnable() {@Overridepublic void run() { Counter.inc(); latch.countDown();} }).start(); } latch.await(); System.out.println('運(yùn)行結(jié)果:'+Counter.count); }}運(yùn)行結(jié)果:98
5、如果在inc方法前面加個(gè)synchronized也能是線程安全的;
它用來(lái)修飾一個(gè)方法或者一個(gè)代碼塊的時(shí)候,能夠保證在同一時(shí)刻最多只有一個(gè)線程執(zhí)行該段代碼。
import java.util.concurrent.CountDownLatch;/** * created by guanguan on 2017/10/23 **/public class Counter { public volatile static Integer count = 0; public synchronized static void inc(){ try{ Thread.sleep(1); //延遲1毫秒 }catch (InterruptedException e){ //catch住中斷異常,防止程序中斷 e.printStackTrace(); } count++;//count值自加1 } public static void main(String[] args) throws InterruptedException { final CountDownLatch latch = new CountDownLatch(100); for(int i=0;i<100;i++){ new Thread(new Runnable() {@Overridepublic void run() { Counter.inc(); latch.countDown();} }).start(); } latch.await(); System.out.println('運(yùn)行結(jié)果:'+Counter.count); }}運(yùn)行結(jié)果:100
synchronized的使用說(shuō)明:
一、當(dāng)兩個(gè)并發(fā)線程訪問(wèn)同一個(gè)對(duì)象object中的這個(gè)synchronized(this)同步代碼塊時(shí),一個(gè)時(shí)間內(nèi)只能有一個(gè)線程得到執(zhí)行。另一個(gè)線程必須等待當(dāng)前線程執(zhí)行完這個(gè)代碼塊以后才能執(zhí)行該代碼塊。
二、然而,當(dāng)一個(gè)線程訪問(wèn)object的一個(gè)synchronized(this)同步代碼塊時(shí),另一個(gè)線程仍然可以訪問(wèn)該object中的非synchronized(this)同步代碼塊。
三、尤其關(guān)鍵的是,當(dāng)一個(gè)線程訪問(wèn)object的一個(gè)synchronized(this)同步代碼塊時(shí),其他線程對(duì)object中所有其它synchronized(this)同步代碼塊的訪問(wèn)將被阻塞。
四、第三個(gè)例子同樣適用其它同步代碼塊。也就是說(shuō),當(dāng)一個(gè)線程訪問(wèn)object的一個(gè)synchronized(this)同步代碼塊時(shí),它就獲得了這個(gè)object的對(duì)象鎖。結(jié)果,其它線程對(duì)該object對(duì)象所有同步代碼部分的訪問(wèn)都被暫時(shí)阻塞。
五、以上規(guī)則對(duì)其它對(duì)象鎖同樣適用.
6、從上面的例子中我們可以看出:使用AtomicInteger是非常的安全的.而且因?yàn)锳tomicInteger由硬件提供原子操作指令實(shí)現(xiàn)的。在非激烈競(jìng)爭(zhēng)的情況下,開(kāi)銷(xiāo)更小,速度更快。
java的關(guān)鍵域有3個(gè)
// setup to use Unsafe.compareAndSwapInt for updates private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final long valueOffset; private volatile int value;
這里, unsafe是java提供的獲得對(duì)對(duì)象內(nèi)存地址訪問(wèn)的類(lèi),注釋已經(jīng)清楚的寫(xiě)出了,它的作用就是在更新操作時(shí)提供“比較并替換”的作用。實(shí)際上就是AtomicInteger中的一個(gè)工具。
valueOffset是用來(lái)記錄value本身在內(nèi)存的便宜地址的,這個(gè)記錄,也主要是為了在更新操作在內(nèi)存中找到value的位置,方便比較。
注意:value是用來(lái)存儲(chǔ)整數(shù)的時(shí)間變量,這里被聲明為volatile,就是為了保證在更新操作時(shí),當(dāng)前線程可以拿到value最新的值(并發(fā)環(huán)境下,value可能已經(jīng)被其他線程更新了)。
這里,我們以自增的代碼為例,可以看到這個(gè)并發(fā)控制的核心算法:
源碼
public final int updateAndGet(IntUnaryOperator updateFunction) { int prev, next; do { prev = get(); next = updateFunction.applyAsInt(prev); } while (!compareAndSet(prev, next)); return next; }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
1. Django視圖類(lèi)型總結(jié)2. Xml簡(jiǎn)介_(kāi)動(dòng)力節(jié)點(diǎn)Java學(xué)院整理3. 使用Docker的NFS-Ganesha鏡像搭建nfs服務(wù)器的詳細(xì)過(guò)程4. Intellij IDEA 關(guān)閉和開(kāi)啟自動(dòng)更新的提示?5. Ajax引擎 ajax請(qǐng)求步驟詳細(xì)代碼6. 解析原生JS getComputedStyle7. idea重置默認(rèn)配置的方法步驟8. IntelliJ IDEA Java項(xiàng)目手動(dòng)添加依賴 jar 包的方法(圖解)9. Django使用HTTP協(xié)議向服務(wù)器傳參方式小結(jié)10. Spring @Profile注解實(shí)現(xiàn)多環(huán)境配置
