2013-01-04 242 views
-1

我創建了一個試圖模擬多線程應用程序的測試包。假設有N個線程訪問共享資源,在這種情況下,這種方法會對整數進行遞增並檢查整數是奇數還是偶數。我試圖實現的是,當方法結果等於50時,監視該值的線程應該能夠停止所有線程並關閉進程。我希望這給大家一個清晰的畫面。現在我遇到的問題是結果有時會不一樣,它們不一致。以下是我寫的代碼。我已經使用了最可能的線程安全措施,所以我相信。是Java併發性:與結果不一致

public class ThreadTestOne { 

private static final java.util.concurrent.atomic.AtomicInteger number= new java.util.concurrent.atomic.AtomicInteger(0); 
private static boolean stop=false; 
private static String orginaltime=gettime("hh:mm:ss"); 

static { 
    try{ 

     java.util.concurrent.ExecutorService executor = java.util.concurrent.Executors.newFixedThreadPool(6); 
     executor.execute(new MasterThread(executor)); 
     executor.execute(new Thread(new child1(),"Thread1")); 
     executor.execute(new Thread(new child2(),"Thread2")); 
     executor.execute(new Thread(new child3(),"Thread3")); 
     executor.execute(new Thread(new child4(),"Thread4")); 
     executor.execute(new Thread(new child5(),"Thread5")); 

    }catch(Exception e){ 
     e.printStackTrace(); 
    } 
} 

private static final class child1 implements java.lang.Runnable{ 
    public void run(){ 
     while(stop!=true){ 
      try{ 
       getCount(this.getClass().getSimpleName()); 
       Thread.sleep(0000); 
      }catch(java.lang.InterruptedException e){ 
      }catch(Exception e){ 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

private static final class child2 implements java.lang.Runnable{ 
    public void run(){ 
     while(stop!=true){ 
      try{ 
       getCount(this.getClass().getSimpleName()); 
       Thread.sleep(0000); 
      }catch(java.lang.InterruptedException e){ 
      }catch(Exception e){ 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

private static final class child3 implements java.lang.Runnable{ 
    public void run(){ 
     while(stop!=true){ 
      try{ 
       getCount(this.getClass().getSimpleName()); 
       Thread.sleep(0000); 
      }catch(java.lang.InterruptedException e){ 
      }catch(Exception e){ 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

private static final class child4 implements java.lang.Runnable{ 
    public void run(){ 
     while(stop!=true){ 
      try{ 
       getCount(this.getClass().getSimpleName()); 
       Thread.sleep(0000); 
      }catch(java.lang.InterruptedException e){ 
      }catch(Exception e){ 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

private static final class child5 implements java.lang.Runnable{ 
    public void run(){ 
     while(stop!=true){ 
      try{ 
       getCount(this.getClass().getSimpleName()); 
       Thread.sleep(0000); 
      }catch(java.lang.InterruptedException e){ 
      }catch(Exception e){ 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

private static final class MasterThread implements java.lang.Runnable{ 
    private java.util.concurrent.ExecutorService MasterExecutor=null; 
    private MasterThread(java.util.concurrent.ExecutorService executor){ 
     this.MasterExecutor=executor; 
    } 
    public void run(){ 
     while(stop!=true){ 
      if(ThreadTestOne.getCurrNumber()==50){ 
       stop=true; 
       MasterExecutor.shutdown(); 
       System.out.println("Amount of time taken to execute is " +ThreadTestOne.elapsedTime(orginaltime)+ " seconds"); 
       System.exit(0); 
      } 
     } 
    } 
} 

private static synchronized void getCount(String ThreadName){ 

    System.out.println(ThreadName+" value is "+incrementgetNumber()+getKind()); 
} 

private static final int incrementgetNumber(){ 

    return number.incrementAndGet(); 
} 

private static final int getCurrNumber(){ 

    return number.get(); 
} 

private static final String getKind(){ 

    return ((getCurrNumber()% 2) == 0) ? " and is an even number." : " and is an odd number."; 
} 

/*private static final void StartThreads(Thread ... threads){ 
    for (Thread thread : threads) { 
     String ThreadName=thread.getName(); 
     long ThreadID=thread.getId(); 
     thread.start(); 
     System.out.println(ThreadName+" of ThreadID: "+ThreadID+" has been Started"); 
    } 
} 

private static final void StopThreads(Thread ... threads){ 
    for (Thread thread : threads) { 
     if(thread!=null){ 
      String ThreadName=thread.getName(); 
      long ThreadID=thread.getId(); 
      System.out.println(ThreadName+" of ThreadID: "+ThreadID+" attempting to stop"); 
      thread.interrupt(); 
      System.out.println(ThreadName+" of ThreadID: "+ThreadID+" stopped"); 
     } 
    } 
}*/ 

private static long elapsedTime(String OriginalTime){ 
    java.text.SimpleDateFormat format = new java.text.SimpleDateFormat("hh:mm:ss"); 
    long difference = 0; 

    try { 
     java.util.Date origTime = format.parse(OriginalTime); 
     java.util.Date currTime = format.parse(gettime("hh:mm:ss")); 
      difference = (currTime.getTime() - origTime.getTime())/1000; 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return difference; 
} 

private static String gettime(String pattern){ 
    String timeString=""; 
    try{ 
    java.text.SimpleDateFormat format = new java.text.SimpleDateFormat(pattern); 
    java.util.Date currentTime = new java.util.Date(); 
    timeString = format.format(currentTime); 
    } 
    catch(Exception e){ 
     e.printStackTrace(); 
    } 
    return timeString; 
} 

public static void main (String []args){ 
    new ThreadTestOne(); 
} 

}

我得到的結果如下

1日試運行

child5 value is 1 and is an odd number. 
child1 value is 2 and is an even number. 
child1 value is 3 and is an odd number. 
child1 value is 4 and is an even number. 
child5 value is 5 and is an odd number. 
child5 value is 6 and is an even number. 
child5 value is 7 and is an odd number. 
child5 value is 8 and is an even number. 
child5 value is 9 and is an odd number. 
child5 value is 10 and is an even number. 
child5 value is 11 and is an odd number. 
child5 value is 12 and is an even number. 
child5 value is 13 and is an odd number. 
child5 value is 14 and is an even number. 
child5 value is 15 and is an odd number. 
child5 value is 16 and is an even number. 
child5 value is 17 and is an odd number. 
child5 value is 18 and is an even number. 
child5 value is 19 and is an odd number. 
child5 value is 20 and is an even number. 
child5 value is 21 and is an odd number. 
child5 value is 22 and is an even number. 
child5 value is 23 and is an odd number. 
child5 value is 24 and is an even number. 
child5 value is 25 and is an odd number. 
child5 value is 26 and is an even number. 
child5 value is 27 and is an odd number. 
child5 value is 28 and is an even number. 
child5 value is 29 and is an odd number. 
child5 value is 30 and is an even number. 
child5 value is 31 and is an odd number. 
child5 value is 32 and is an even number. 
child5 value is 33 and is an odd number. 
child5 value is 34 and is an even number. 
child5 value is 35 and is an odd number. 
child5 value is 36 and is an even number. 
child5 value is 37 and is an odd number. 
child5 value is 38 and is an even number. 
child5 value is 39 and is an odd number. 
child5 value is 40 and is an even number. 
child5 value is 41 and is an odd number. 
child5 value is 42 and is an even number. 
child5 value is 43 and is an odd number. 
child5 value is 44 and is an even number. 
child5 value is 45 and is an odd number. 
child5 value is 46 and is an even number. 
child5 value is 47 and is an odd number. 
child5 value is 48 and is an even number. 
child5 value is 49 and is an odd number. 
child5 value is 50 and is an even number. 
child4 value is 51 and is an odd number. 
child2 value is 52 and is an even number. 
child3 value is 53 and is an odd number. 
child1 value is 54 and is an even number. 
Amount of time taken to execute is 0 seconds 

第二測試運行

child2 value is 112549 and is an odd number. 
child2 value is 112550 and is an even number. 
child2 value is 112551 and is an odd number. 
child2 value is 112552 and is an even number. 
child2 value is 112553 and is an odd number. 
child2 value is 112554 and is an even number. 
child2 value is 112555 and is an odd number. 
child2 value is 112556 and is an even number. 
child2 value is 112557 and is an odd number. 
child2 value is 112558 and is an even number. 
child2 value is 112559 and is an odd number. 
child2 value is 112560 and is an even number. 
child2 value is 112561 and is an odd number. 
child2 value is 112562 and is an even number. 
child2 value is 112563 and is an odd number. 
child2 value is 112564 and is an even number. 
child2 value is 112565 and is an odd number. 
child2 value is 112566 and is an even number. 
child2 value is 112567 and is an odd number. 
child2 value is 112568 and is an even number. 
child2 value is 112569 and is an odd number. 
child2 value is 112570 and is an even number. 
child2 value is 112571 and is an odd number. 
child2 value is 112572 and is an even number. 
child2 value is 112573 and is an odd number. 
child2 value is 112574 and is an even number. 
child2 value is 112575 and is an odd number. 
child2 value is 112576 and is an even number. 
child2 value is 112577 and is an odd number. 
child2 value is 112578 and is an even number. 
child2 value is 112579 and is an odd number. 
child2 value is 112580 and is an even number. 
child2 value is 112581 and is an odd number. 
child2 value is 112582 and is an even number. 
child2 value is 112583 and is an odd number. 
child2 value is 112584 and is an even number. 
child2 value is 112585 and is an odd number. 
child2 value is 112586 and is an even number. 
child2 value is 112587 and is an odd number. 
child2 value is 112588 and is an even number. 
child2 value is 112589 and is an odd number. 
child2 value is 112590 and is an even number. 
child2 value is 112591 and is an odd number. 
child2 value is 112592 and is an even number. 
child2 value is 112593 and is an odd number. 
child2 value is 112594 and is an even number. 
child2 value is 112595 and is an odd number. 
child2 value is 112596 and is an even number. 
child2 value is 112597 and is an odd number. 
child2 value is 112598 and is an even number. 
child2 value is 112599 and is an odd number. 
child2 value is 112600 and is an even number. 
child2 value is 112601 and is an odd number. 
child2 value is 112602 and is an even number. 
child2 value is 112603 and is an odd number. 
child2 value is 112604 and is an even number. 
child2 value is 112605 and is an odd number. 
child2 value is 112606 and is an even number. 
child2 value is 112607 and is an odd number. 
child2 value is 112608 and is an even number. 
child2 value is 112609 and is an odd number. 
child2 value is 112610 and is an even number. 
child2 value is 112611 and is an odd number. 
child2 value is 112612 and is an even number. 
child2 value is 112613 and is an odd number. 
child2 value is 112614 and is an even number. 
child2 value is 112615 and is an odd number. 
child2 value is 112616 and is an even number. 
child2 value is 112617 and is an odd number. 
child2 value is 112618 and is an even number. 
child2 value is 112619 and is an odd number. 
child2 value is 112620 and is an even number. 
child2 value is 112621 and is an odd number. 
child2 value is 112622 and is an even number. 
child2 value is 112623 and is an odd number. 
child2 value is 112624 and is an even number. 
child2 value is 112625 and is an odd number. 
child2 value is 112626 and is an even number. 
child2 value is 112627 and is an odd number. 
child2 value is 112628 and is an even number. 
child2 value is 112629 and is an odd number. 
child2 value is 112630 and is an even number. 
child2 value is 112631 and is an odd number. 
child2 value is 112632 and is an even number. 
child2 value is 112633 and is an odd number. 
child2 value is 112634 and is an even number. 
child2 value is 112635 and is an odd number. 
child2 value is 112636 and is an even number. 
child2 value is 112637 and is an odd number. 
child2 value is 112638 and is an even number. 
child2 value is 112639 and is an odd number. 
child2 value is 112640 and is an even number. 
child2 value is 112641 and is an odd number. 
child2 value is 112642 and is an even number. 
child2 value is 112643 and is an odd number. 
child2 value is 112644 and is an even number. 

3日試運行

child4 value is 1 and is an odd number. 
child1 value is 2 and is an even number. 
child3 value is 3 and is an odd number. 
child3 value is 4 and is an even number. 
child3 value is 5 and is an odd number. 
child3 value is 6 and is an even number. 
child3 value is 7 and is an odd number. 
child3 value is 8 and is an even number. 
child3 value is 9 and is an odd number. 
child3 value is 10 and is an even number. 
child3 value is 11 and is an odd number. 
child3 value is 12 and is an even number. 
child3 value is 13 and is an odd number. 
child3 value is 14 and is an even number. 
child3 value is 15 and is an odd number. 
child3 value is 16 and is an even number. 
child3 value is 17 and is an odd number. 
child3 value is 18 and is an even number. 
child3 value is 19 and is an odd number. 
child3 value is 20 and is an even number. 
child3 value is 21 and is an odd number. 
child3 value is 22 and is an even number. 
child3 value is 23 and is an odd number. 
child3 value is 24 and is an even number. 
child3 value is 25 and is an odd number. 
child3 value is 26 and is an even number. 
child3 value is 27 and is an odd number. 
child3 value is 28 and is an even number. 
child3 value is 29 and is an odd number. 
child3 value is 30 and is an even number. 
child3 value is 31 and is an odd number. 
child3 value is 32 and is an even number. 
child3 value is 33 and is an odd number. 
child3 value is 34 and is an even number. 
child3 value is 35 and is an odd number. 
child3 value is 36 and is an even number. 
child3 value is 37 and is an odd number. 
child3 value is 38 and is an even number. 
child3 value is 39 and is an odd number. 
child3 value is 40 and is an even number. 
child3 value is 41 and is an odd number. 
child3 value is 42 and is an even number. 
child3 value is 43 and is an odd number. 
child3 value is 44 and is an even number. 
child3 value is 45 and is an odd number. 
child3 value is 46 and is an even number. 
child3 value is 47 and is an odd number. 
child3 value is 48 and is an even number. 
child3 value is 49 and is an odd number. 
child3 value is 50 and is an even number. 
Amount of time taken to execute is 0 seconds 
child2 value is 51 and is an odd number. 

如果你看一下第1和第3的測試運行,你會看到線程繼續50大關已經達到甚至後執行。 第二次測試運行令人困惑。請提出問題可能是什麼?

+3

併發中唯一的一致性往往是不一致。至少,「stop」需要標記爲「volatile」。雖然這不會起到什麼作用,但實際上,因爲'主線程'正在訪問'number'時沒有任何保證,即使它正在被安全地更新。您需要重新設計應用程序的工作方式。 –

+0

@ Clockwork-Muse感謝您的建議,我實際上已經忘記將揮發性添加到布爾,笨拙的我。讓我看看如何保證數字檢查。 – kimathie

回答

2

stop必須是易失性的,以便對其進行修改以保證在線程間可見。

請注意,由於主線程檢查和停止操作不是原子的,因此每次運行仍然不會有完全50個結果。另外,主線程永遠不會看到完全等於50的值,在這種情況下它將永遠運行。

+0

感謝您的建議,我已經看到我的錯誤在哪裏。 – kimathie

0

所以我確實接受了@jtahlborn和@ Clockwork-Muse的建議,並提出了以下建議。

public class ThreadTestOne { 

private static final java.util.concurrent.atomic.AtomicInteger number= new java.util.concurrent.atomic.AtomicInteger(1); 
private static final java.util.concurrent.atomic.AtomicBoolean stop= new java.util.concurrent.atomic.AtomicBoolean(false); 
private static final int max=50; 
private static final long sleepTime=0000; 
private static String orginaltime=gettime("hh:mm:ss"); 

static { 
    try{ 

     java.util.concurrent.ExecutorService executor = java.util.concurrent.Executors.newFixedThreadPool(6); 
     executor.execute(new MasterThread(executor)); 
     executor.execute(new Thread(new child1("Thread1"))); 
     executor.execute(new Thread(new child2("Thread2"))); 
     executor.execute(new Thread(new child3("Thread3"))); 
     executor.execute(new Thread(new child4("Thread4"))); 
     executor.execute(new Thread(new child5("Thread5"))); 

    }catch(Exception e){ 
     e.printStackTrace(); 
    } 
} 

private static final class child1 implements java.lang.Runnable{ 
    private String threadName=""; 
    private child1(String threadName){ 
     this.threadName=threadName; 
    } 
    public void run(){ 
     Thread.currentThread().setName(threadName); 
     while(true){ 
      try{ 
       getNumber(Thread.currentThread().getName()); 
       Thread.sleep(sleepTime); 
      }catch(java.lang.InterruptedException e){ 
      }catch(Exception e){ 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

private static final class child2 implements java.lang.Runnable{ 
    private String threadName=""; 
    private child2(String threadName){ 
     this.threadName=threadName; 
    } 

    public void run(){ 
     Thread.currentThread().setName(threadName); 
     while(true){ 
      try{ 
       getNumber(Thread.currentThread().getName()); 
       Thread.sleep(sleepTime); 
      }catch(java.lang.InterruptedException e){ 
      }catch(Exception e){ 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

private static final class child3 implements java.lang.Runnable{ 
    private String threadName=""; 
    private child3(String threadName){ 
     this.threadName=threadName; 
    } 

    public void run(){ 
     Thread.currentThread().setName(threadName); 
     while(true){ 
      try{ 
       getNumber(Thread.currentThread().getName()); 
       Thread.sleep(sleepTime); 
      }catch(java.lang.InterruptedException e){ 
      }catch(Exception e){ 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

private static final class child4 implements java.lang.Runnable{ 
    private String threadName=""; 
    private child4(String threadName){ 
     this.threadName=threadName; 
    } 

    public void run(){ 
     Thread.currentThread().setName(threadName); 
     while(true){ 
      try{ 
       getNumber(Thread.currentThread().getName()); 
       Thread.sleep(sleepTime); 
      }catch(java.lang.InterruptedException e){ 
      }catch(Exception e){ 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

private static final class child5 implements java.lang.Runnable{ 
    private String threadName=""; 
    private child5(String threadName){ 
     this.threadName=threadName; 
    } 

    public void run(){ 
     Thread.currentThread().setName(threadName); 
     while(true){ 
      try{ 
       getNumber(Thread.currentThread().getName()); 
       Thread.sleep(sleepTime); 
      }catch(java.lang.InterruptedException e){ 
      }catch(Exception e){ 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

private static final class MasterThread implements java.lang.Runnable{ 
    private java.util.concurrent.ExecutorService MasterExecutor=null; 
    private MasterThread(java.util.concurrent.ExecutorService executor){ 
     this.MasterExecutor=executor; 
    } 
    public void run(){ 
     while(true){ 
      if(stop.get()!=false){ 
       MasterExecutor.shutdown(); 
       System.out.println("Amount of time taken to execute is " +ThreadTestOne.elapsedTime(orginaltime)+ " seconds"); 
       System.exit(0); 
      } 
     } 
    } 
} 

public static synchronized void getNumber(String ThreadName){ 
    String result=""; 
    if(number.get()!=max){ 
     result=((number.get()%2)==0)?" and is an even number.":" and is an odd number."; 
     System.out.println(ThreadName+" value is "+number.get()+result); 
     number.incrementAndGet(); 
    }else{ 
     stop.set(true); 
    } 
} 

private static long elapsedTime(String OriginalTime){ 
    java.text.SimpleDateFormat format = new java.text.SimpleDateFormat("hh:mm:ss"); 
    long difference = 0; 
    try { 
     java.util.Date origTime = format.parse(OriginalTime); 
     java.util.Date currTime = format.parse(gettime("hh:mm:ss")); 
      difference = (currTime.getTime() - origTime.getTime())/1000; 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return difference; 
} 

private static String gettime(String pattern){ 
    String timeString=""; 
    try{ 
    java.text.SimpleDateFormat format = new java.text.SimpleDateFormat(pattern); 
    java.util.Date currentTime = new java.util.Date(); 
    timeString = format.format(currentTime); 
    } 
    catch(Exception e){ 
     e.printStackTrace(); 
    } 
    return timeString; 
} 

public static void main (String []args){ 
    new ThreadTestOne(); 
} 

}

的解決方案,現在的操作是保證現在是在它的結果是一致的。謝謝你們,我希望這會對其他學習java併發的人有利。