2013-01-04 251 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并发的人有利。