<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    天天看海

    每天都想看海

    一個能夠證明i++在多線程下非原子化的例子及其改進

    主程序運行1000個子線程(太少了結果不容易出來),每個子線程執行指向同一整數引用的i++,當1000個子線程運行完畢后,主線程繼續運行,輸出最終的i值。很顯然,如果最終輸出的結果i值不等于1000,那么中間i++操作一定被分解了。程序代碼如下:

    【版本一】

    import cn.yuzhe.multi.util.AllFinished;

    public class ThreadSafeClass {

    public static void main(String[] args) {
             
    //要創建的子線程數
                 int threadNum=1000;                          
      
             
    //每個子線程都要引用的對象
                 A_Integer bb=new A_Integer();
      
            
    //創建能判斷所有子線程是否結束的對象,用于保證主線程能在多有子線程都結束后再執行余下的代碼,
                 
    //防止主線程提前于子線程結束
                 AllFinished af=new AllFinished(threadNum);  
      
             
    //創建多個子線程對象
                 NoAtomicIntegerThread[] at=new NoAtomicIntegerThread[threadNum];
      
                 
    for(int i=0;i<threadNum;i++){
                       at[i]
    =new NoAtomicIntegerThread(bb,i,af);
                 }

      
                 
    for(int i=0;i<threadNum;i++){
                       at[i].start();
                 }
     
      
                 
    while(true){
                       
    if( af.isAllFinished() ){
                             System.out.println(
    "主線程運行結束,應該獲得的最終值為"+threadNum
                                              
    +";實際最終值為"+bb.int_I);
                             
    break;
                       }

       
                      
    int sleep=500;    //睡眠一段時間,釋放時間片
                      try {
                            Thread.sleep(sleep);
                      }
     catch (InterruptedException e) {
                            e.printStackTrace();
                      }

                 }
     
             }

    }


    class NoAtomicIntegerThread extends Thread{
              
    public A_Integer jj;
              
    private int id;
              
    private AllFinished af;

    public void run() {
                 jj.int_I
    ++;
                 af.setItemFinished(id);
    //           System.out.println(jj.int_I);              //輸出中間結果
    }


    public NoAtomicIntegerThread(A_Integer __j,int _id,AllFinished _af) {
                 
    super();
                 
    this.jj=__j;
                 
    this.id=_id;
                 
    this.af=_af;
    }

    }


    class A_Integer
    {
                
    public int int_I=0;
    }



    這里要用到一個我自己定義的util類:

    /**
    @author 紅樓無夢,JAVA多線程QQ群:34237757
    * Date:2008-8-13 09:28
    * Function: 主線程創建多個分線程,保證主線程在所有分線程都結束后才能運行余下的代碼,直至結束。
    */

    public class AllFinished {
                
    private boolean[] isItemsFinished;
                
    private int num;

                
    public AllFinished(int itemNum) {
                      
    super();
      
                      num
    =itemNum;
                      isItemsFinished
    =new boolean[num];
                      
    for(int i=0;i<num;i++)
                            isItemsFinished[i]
    =false;
                }


                
    public synchronized boolean setItemFinished(int i)
                
    {
                      
    if(i>=num)
                            
    return false;
                      
    this.isItemsFinished[i]=true;
                      
    return true;
                }


                
    public synchronized boolean isAllFinished()
                
    {
                      
    for(int i=0;i<num;i++){
                            
    if(!this.isItemsFinished[i])
                                  
    return false;
                      }

                      
    return true;
                }

    }


    例子需要運行多次才能看到結果,當實際結果和理想結果不一樣的時候,很顯然,i++被分解了,結果的部分輸入如下:
    ......
    996
    997
    998
    主線程運行結束,應該獲得的最終值為1000;實際最終值為998。

    =====================================================
    【改進一】下面的代碼用AtomicInteger進行了改進,使得i++操作被原子化,代碼如下:

    public class ThreadSafeClass {

              
    public static void main(String[] args) {
          
    //要創建的子線程數
              int threadNum=1000;                          
      
          
    //每個子線程都要引用的對象
              AtomicInteger bb=new AtomicInteger(0);
      
          
    //創建能判斷所有子線程是否結束的對象,用于保證主線程能在多有子線程都結束后再執行余下的代碼,
              
    //防止主線程提前于子線程結束
              AllFinished af=new AllFinished(threadNum);  
      
          
    //多個子線程對象
              AtomicIntegerThread[] at=new AtomicIntegerThread[threadNum];
      
              
    for(int i=0;i<threadNum;i++){
                   at[i]
    =new AtomicIntegerThread(bb,i,af);
              }

      
              
    for(int i=0;i<threadNum;i++){
                   at[i].start();
              }
     
      
              
    while(true){
                   
    if(af.isAllFinished()){
                        System.out.println(
    "主線程運行結束,應該獲得的最終值為"+threadNum
                                                  
    +";實際最終值為"+bb);
                    
    break;
                   }

       
                   
    int sleep=(int)(Math.random()*500);
                   
    try {
                        Thread.sleep(sleep);
                   }
     catch (InterruptedException e) {
                        e.printStackTrace();
                   }

              }
     
    }

    }


    class AtomicIntegerThread extends Thread{
            
    private int id;
            
    private AllFinished af;
            
    public AtomicInteger j;

             
    public AtomicIntegerThread(AtomicInteger __j,int _id,AllFinished _af) {
                  
    super();
                  
    this.j=__j;
                  
    this.id=_id;
                  
    this.af=_af;
             }



             
    public void run() 
                    j.getAndIncrement();
                   af.setItemFinished(id);
                   System.out.println(j); 
    //這里輸出沒有同步,很可能會出現不一致,這里僅僅用來測試一下,正好能證明線程將操作分解^_^   
             }

    }



    運行了多次沒有出現被分解的情況,最后我把線程數從一千改成一萬,又增加到十萬,并且運行多次,沒有出現結果和預計結果不一致的情況。十萬個線程啊!如果能分解的話早把程序分得七零八碎了,呵呵。某次結果如下:
    ......
    99994
    99993
    99992
    主線程運行結束,應該獲得的最終值為100000;實際最終值為100000
    =====================================================
    【改進二】群友TITAN的方法更簡單,在版本一的基礎上加上一小段代碼

    class NoAtomicIntegerThread extends Thread{


          
    public void run() {
              
    synchronized(jj){
                        jj.int_I
    ++;
              }

                af.setItemFinished(id);
                System.out.println(jj.int_I);
    }



    }



    我對比了一下改進一和改進二,在十萬個線程并發情況下,二者的運行速度幾乎沒有差別。可見JAVA類庫中的AtomicInteger還是很實用的。

    大伙有什么改進的方法,歡迎大家提意見。yuzhe80@126.com

    ******************************************************************************
    后話:這里為了保證主線程在子線程都執行完后再繼續執行,特意定義了一個類AllFinished,記錄每個子線程是否結束,其實大可不必,因為JAVA中對線程有join函數,在main函數中改成這樣就可以了。

    public class ThreadSafeClass {
           
    public static void main(String[] args) {
          
    //要創建的子線程數
           int threadNum=1000;                          
      
          
    //每個子線程都要引用的對象
           AtomicInteger bb=new AtomicInteger(0);
      
          
    //多個子線程對象
           AtomicIntegerThread[] at=new AtomicIntegerThread[threadNum];
      
           
    for(int i=0;i<threadNum;i++){
                at[i]
    =new AtomicIntegerThread(bb,i);
           }

      
           
    long last=System.currentTimeMillis();
           
    for(int i=0;i<threadNum;i++){
                at[i].start();
           }
     
      
           
    for(int i=0;i<threadNum;i++){
                
    try {
                     at[i].join();                                     
    //保證主線程在所有子線程結束后再執行
                }
     catch (InterruptedException e) {
                     e.printStackTrace();
                }

           }
     
      
           System.out.println(
    "主線程運行結束,應該獲得的最終值為"+threadNum
           
    +";實際最終值為"+bb+"程序運行時間"+(System.currentTimeMillis()-last)+"毫秒");

          }

    }



    而且這樣修改,在性能上有很大提升,用我自定義的類AllFinished,運行1000個線程,平均時間為2100ms,而用join函數,平均時間為1600ms,性能提升了25%。以后還是推薦大伙使用join吧^_^

    posted on 2007-08-13 16:56 天天看海 閱讀(377) 評論(0)  編輯  收藏


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    導航

    統計

    留言簿

    文章檔案

    搜索

    最新評論

    主站蜘蛛池模板: 亚洲国产成人久久一区久久| 毛片a级毛片免费观看免下载| 免费永久看黄在线观看app| 精品亚洲成A人无码成A在线观看 | 免费福利在线观看| 四虎成人精品在永久免费 | 成人a毛片免费视频观看| 免费在线黄色网址| 一级一黄在线观看视频免费| 在线亚洲精品福利网址导航| 特级做A爰片毛片免费看无码| 久久精品国产99精品国产亚洲性色| 可以免费观看的毛片| 久久综合亚洲鲁鲁五月天| 亚洲免费福利在线视频| 中国china体内裑精亚洲日本| 日韩成人免费在线| 好猛好深好爽好硬免费视频| 亚洲欧洲日产国产综合网| 美女被免费喷白浆视频| 亚洲成a人无码亚洲成av无码| 亚洲国产成人精品无码久久久久久综合| 一区二区三区免费看| 亚洲AV无码精品色午夜在线观看| 欧洲精品99毛片免费高清观看| 亚洲乱码一区av春药高潮| 免费人成在线观看网站品爱网日本| 51午夜精品免费视频| 亚洲国产成人精品久久 | 亚洲熟妇无码八AV在线播放| 无码精品一区二区三区免费视频| 亚洲人成综合在线播放| 国产成人在线观看免费网站| 中文在线观看免费网站| 亚洲国产精品午夜电影| 国产成人无码免费视频97| 日韩免费无码视频一区二区三区| 亚洲精品国产摄像头| 久久久久久a亚洲欧洲aⅴ| 福利免费观看午夜体检区| 一级毛片完整版免费播放一区|