-1

我创建了一个尝试模拟多线程应用程序的测试包。假设有 N 个线程访问共享资源,在这种情况下,该方法将对整数进行增量并检查整数是奇数还是偶数。我想要实现的是当方法结果等于 50 时,正在监视该值的线程应该能够停止所有线程并关闭进程。我希望这能给每个人一个清晰的画面。现在我遇到的问题是结果不时不同,它们不一致。下面是我写的代码。我已经使用了尽可能多的线程安全措施,所以我相信。

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();
}

}

我得到的结果如下

第一次试运行

    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.

第三次试运行

    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 标记后线程仍继续执行。第二次试运行令人困惑。请提出问题可能是什么?

4

2 回答 2

2

stop必须是 volatile 才能保证对它的修改在线程间可见。

请注意,由于主线程检查和停止操作不是原子操作,因此每次运行仍然不会正好有 50 个结果。此外,主线程完全有可能永远不会看到恰好等于 50 的值,在这种情况下它将永远运行。

于 2013-01-04T20:24:12.387 回答
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并发的人有所帮助。

于 2013-01-05T08:37:34.363 回答