更新時間:2020-11-06 17:44:58 來源:動力節點 瀏覽1286次
原子性操作,即為最小的操作單元,比如i=1,就是一個原子性操作,這個過程只涉及一個賦值操作。多線程原子性操作依賴在J.U.C包下的atomic系列的類。它主要包括四類:基本類型,數組類型,屬性原子修改器類型,引用類型。
1.基本類型的實現:
package concurrent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicTest {
private static final AtomicInteger at=new AtomicInteger();
private static final ExecutorService es=Executors.newFixedThreadPool(20);
public static void main(String[] args) {
// TODO Auto-generated method stub
long start=System.currentTimeMillis();
for(int i=0;i<1000;i++)
{
Thread t1=new Thread() {
public void run()
{
System.out.println(Thread.currentThread().getName()+"實現了一次自增原子操作,結果為:"+at.incrementAndGet());
}
};
es.execute(t1);
}
try
{
Thread.sleep(5000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
System.out.println("計算過程的耗時為:"+(System.currentTimeMillis()-start-5000));
System.out.println("累加1000次,得到結果"+at);
}
}
運行結果如下:
pool-1-thread-13實現了一次自增原子操作,結果為:984
pool-1-thread-8實現了一次自增原子操作,結果為:983
pool-1-thread-14實現了一次自增原子操作,結果為:982
pool-1-thread-20實現了一次自增原子操作,結果為:981
pool-1-thread-10實現了一次自增原子操作,結果為:980
pool-1-thread-12實現了一次自增原子操作,結果為:979
pool-1-thread-3實現了一次自增原子操作,結果為:978
pool-1-thread-7實現了一次自增原子操作,結果為:977
pool-1-thread-4實現了一次自增原子操作,結果為:976
pool-1-thread-18實現了一次自增原子操作,結果為:1000
pool-1-thread-9實現了一次自增原子操作,結果為:999
pool-1-thread-17實現了一次自增原子操作,結果為:998
pool-1-thread-6實現了一次自增原子操作,結果為:997
pool-1-thread-5實現了一次自增原子操作,結果為:996
pool-1-thread-2實現了一次自增原子操作,結果為:995
計算過程的耗時為:9
累加1000次,得到結果1000
由上面可知使用基本類型的原子操作類進行數字的自增,不僅可以保證操作操作的原子性,而且相對來說花費的時間代價比使用synchronized加鎖的時間代價要小。
2.數組類型
以下以AtomicIntegerArray為例通過對一個數組內的每個元素進行自增計算,從而來介紹數組類型的原子類的運用。
package concurrent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicIntegerArray;
public class AtomicTest {
private static final AtomicIntegerArray at=new AtomicIntegerArray(new int[5]);
private static final ExecutorService es=Executors.newFixedThreadPool(20);
public static void main(String[] args) {
// TODO Auto-generated method stub
long start=System.currentTimeMillis();
for(int i=0;i<1000;i++)
{
Thread t1=new Thread() {
public void run()
{
for(int i=0;i<5;i++)
System.out.println(Thread.currentThread().getName()+"實現了對第"+(i+1)+"個元素一次自增原子操作,結果為:"+at.incrementAndGet(i));
}
};
es.execute(t1);
}
try
{
Thread.sleep(5000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
System.out.println("計算過程的耗時為:"+(System.currentTimeMillis()-start-5000));
for(int i=0;i<5;i++)
System.out.println("第"+(i+1)+"個元素累加1000次,得到結果"+at.get(i));
}
}
運行程序結果如下,其中運算過程部分給出:
pool-1-thread-3實現了對第5個元素一次自增原子操作,結果為:980
pool-1-thread-20實現了對第1個元素一次自增原子操作,結果為:989
pool-1-thread-20實現了對第2個元素一次自增原子操作,結果為:1000
pool-1-thread-20實現了對第3個元素一次自增原子操作,結果為:1000
pool-1-thread-20實現了對第4個元素一次自增原子操作,結果為:1000
pool-1-thread-20實現了對第5個元素一次自增原子操作,結果為:1000
pool-1-thread-15實現了對第5個元素一次自增原子操作,結果為:998
計算過程的耗時為:9
第1個元素累加1000次,得到結果1000
第2個元素累加1000次,得到結果1000
第3個元素累加1000次,得到結果1000
第4個元素累加1000次,得到結果1000
第5個元素累加1000次,得到結果1000
從結果可以看出,數組類型的原子類的使用,可以保證每個元素的自增等操作都滿足原子性。
3.屬性原子修改器
以AtomicIntegerFieldUpdater類為例,該類有一個靜態方法newUpdater(Class tclass,String fieldName),則這個表示為tclass類的fieldName屬性創建一個屬性原子修改器,如果需要修改該屬性,則只需要調用原子修改器的方法,比如addAndGet(tclass obj,int delta):該方法表示將該修改器對應的屬性增加delta。以下通過代碼來了解屬性原子修改器的作用。
package concurrent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
class Count{
public volatile int number;
}
public class AtomicTest {
private static final AtomicIntegerFieldUpdater
private static final ExecutorService es=Executors.newFixedThreadPool(20);
public static void main(String[] args) {
// TODO Auto-generated method stub
final Count count=new Count();
long start=System.currentTimeMillis();
for(int i=0;i<1000;i++)
{
Thread t1=new Thread() {
public void run()
{
System.out.println(Thread.currentThread().getName()+"實現了一次自增原子操作,結果為:"+aifu.addAndGet(count, 1));
}
};
es.execute(t1);
}
try
{
Thread.sleep(5000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
System.out.println("計算過程的耗時為:"+(System.currentTimeMillis()-start-5000));
for(int i=0;i<5;i++)
System.out.println("第"+(i+1)+"個元素累加1000次,得到結果"+count.number);
}
}
運行以上程序,得到如下結果:
pool-1-thread-17實現了一次自增原子操作,結果為:993
pool-1-thread-5實現了一次自增原子操作,結果為:992
pool-1-thread-19實現了一次自增原子操作,結果為:991
pool-1-thread-3實現了一次自增原子操作,結果為:990
pool-1-thread-15實現了一次自增原子操作,結果為:989
pool-1-thread-20實現了一次自增原子操作,結果為:988
pool-1-thread-18實現了一次自增原子操作,結果為:987
pool-1-thread-6實現了一次自增原子操作,結果為:986
pool-1-thread-7實現了一次自增原子操作,結果為:985
pool-1-thread-9實現了一次自增原子操作,結果為:984
計算過程的耗時為:10
第1個元素累加1000次,得到結果1000
第2個元素累加1000次,得到結果1000
第3個元素累加1000次,得到結果1000
第4個元素累加1000次,得到結果1000
第5個元素累加1000次,得到結果1000
從上面結果可以看出,屬性原子修改器的使用也能達到原子性操作的目的。
4.引用類型
以AtomicReference類為例,通過AtomicReference
package concurrent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference;
class Count{
public int count;
public Count(int count)
{
this.count=count;
}
public String toString()
{
return "這個對象的位置是:"+count;
}
}
public class AtomicTest {
private static final AtomicReference
public static void main(String[] args) {
// TODO Auto-generated method stub
Count count=new Count(1001);
long start=System.currentTimeMillis();
ar.set(count);
System.out.println("你好,"+ar.get());
Count count1=new Count(1002);
ar.compareAndSet(count, count1);//內存值與count是一樣的,所以值更新為count1
System.out.println("我發生了改變:"+ar.get());
Count count2=new Count(1003);
ar.compareAndSet(count, count2);//此時內存智為count1,與count不一致,所以無法更新,因此內存值依然為count1
System.out.println("我發生了改變:"+ar.get());
}
}
運行程序,結果如下:
你好,這個對象的位置是:1001
我發生了改變:這個對象的位置是:1002
我發生了改變:這個對象的位置是:1002
以上就是Java多線程原子性操作的實現,總而言之,就是依賴atomic系列類來實現的。基本類型的類主要包括AtomicInteger、AtomicLong、AtomicBoolean等;數組類型主要包括AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray;屬性原子修改器類型主要包括AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater ;引用類型主要包括AtomicReference、AtomicStampedRerence、AtomicMarkableReference。對于這些類的具體講解可以參照本站的Java多線程教程加以學習。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習