• <nav id="wkkge"><strong id="wkkge"></strong></nav>
  • <menu id="wkkge"></menu>
  • 首頁 > hot資訊 > 實現多線程原子性操作

    實現多線程原子性操作

    更新時間:2020-11-06 17:44 瀏覽116次 來源:動力節點

    原子性操作,即為最小的操作單元,比如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 AtomicIntegerFieldUpdateraifu=AtomicIntegerFieldUpdater.newUpdater(Count.class, "number");

    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類為例,通過AtomicReferencear=new AtomicReference<>();ar可以調用set()方法設置初始值,調用compareAndSet(expect,update):這個方法就是將存在ar中的值與expect值作比較,如果兩者相等,則更新該值為update;代碼如下:

    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 AtomicReferencear=new 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多線程教程加以學習。


    相關文章推薦
    HOT資訊 >

    熱門課程推薦

    全部班型支持免費試學

    動力節點在線報名表(此信息已加密,請放心填寫)

    返回頂部
  • <nav id="wkkge"><strong id="wkkge"></strong></nav>
  • <menu id="wkkge"></menu>
  • 面对面棋牌游戏