Results 1 to 4 of 4
  1. #1
    duster is offline Member
    Join Date
    Oct 2012
    Posts
    3
    Rep Power
    0

    Default developing a notquite- Trivial Java application using threads

    Total marks on this assignment: 80. This assignment counts 8% of total marks.

    Learning goals: by completing this assignment, you’ll get some practical experience with writing
    JUnit tests, with porting and debugging Java programs written by others, with developing a notquite-
    Trivial Java application using threads, and with exploring the performance of heavily multithreaded
    computations on a desktop or laptop computer.

    Asking for help. If you become confused by Java syntax or semantics, or if you have difficulty using
    your Java development environment, you should look on the internet or ask anyone for help. If you
    do not understand the underlying concepts, such as the nature of a “test case”, you should start by
    reviewing the assigned readings and lecture slides; but you are welcome to seek assistance from
    others on “learning the concepts” after you have done your assigned readings for this course.

    Working independently. You are not allowed to have assistance from any other person, or from the
    internet, when you are writing your test cases, when you are interpreting your test results, when
    you are designing your code, and when you are writing your code. All of this must be your own
    work, done independently. If you have difficulty debugging, you may seek assistance from tutors or
    lab assistants – they should not be telling you “how to fix your bug”, but they may be able to give
    you some helpful and appropriate advice (for example, on what you could do to localise the defect,
    or on what topic you should study which might help you figure out how to debug your own
    program).

    Resource requirements. This assignment can be completed if you are using only the basic javac/java
    support provided in any recent SDK for Java. However you may wish take this opportunity to learn
    how to use an IDE such as Eclipse -- if you don’t know how to do so already.

    1.

    In the Assignment 2 resources area of the Knowledge Map of the Cecil-site for CompSci 230,
    you will find my transcription of Appendix A of the 2nd edition of Myers’ monograph on The
    Art of Software Testing. This is a simple Java program (check4Prime.java) with seven
    test cases (check4PrimeTest.java). Myers provides instructions for how to use a
    command-line interface to Java in his Appendix A – you should read his instructions

    Myers apparently used JUnit 3 and J2SE 1.4 when developing his code. You may use either
    JUnit 3 or JUnit 4 to complete this question, and you may use any recent version of SE 1.6 or
    SE 1.7.

    a. (10 marks)
    b. Develop an acceptance test for an import of check4Prime.java into
    your development system. Your test should be described informally, but in enough
    detail that another person – in particular the person who marks your assignment! –
    can understand what you did. Your test should confirm that you are able to compile
    and run this 8-year-old code (which was developed for an earlier version of Java) on
    your system. Your test should be quite simple – taking at most a minute or two to
    run.

    Submit two or three items:

    i. Your acceptance test: describe what input you presented to your build of
    check4Prime.java, what output you expected, whether or not your
    test was successful, and whether you observed anything extraordinary
    about your development system while running this test.

    ii. A description of your Java system, including the version numbers of your
    SDK, your operating system, and any other software that might reasonably
    be expected to affect the success of your importation.

    iii. Submit this only if your acceptance test was unsuccessful: describe what you
    did to try to identify the defect. If you were able to successfully import a
    modified version of check4Prime.java, describe your modifications.

    b. (6 marks) Develop an acceptance test for an import of check4PrimeTest.java
    into your development system. Submit either two or three items, as for question 1a
    above, depending on whether or not your importation was successful.
    c. (9 marks) Develop two new test cases for check4PrimeTest.java.

    Submit:
    i. Your justification for your new cases, explaining the type(s) of errors you
    were hoping to find when you designed these tests.
    ii. The JUnit code for your test cases.
    iii. A test report, indicating what happened when you ran these tests, anything
    extraordinary you noticed while running your tests, and your interpretation
    of your test results.

    2. (55 marks, in total) In the Assignment 2 resources area of the Knowledge Map of the Cecilsite
    for CompSci 230, you will find PrimeRace.jar This is a Java application with six classfiles.
    a. (5 marks) Acceptance Testing. Download PrimeRace.jar into your development
    area, and run the following tests.
    i. The command “java primea2/PrimeRace“ prints a help message;
    ii. The command “java primea2/PrimeRace 1000 1 10” runs for
    approximately one second and prints approximately 6 lines of output;
    iii. The command “javac primea2/*.java” creates a new set of classfiles
    which pass tests i. and ii. above.

    Submit: Your test report, which should have the following content.
    i. A brief description of the relevant aspects of your software configuration,
    for example the version number of your Java SDK.
    ii. A brief description of your hardware configuration: your operating system,
    CPU model, the maximum clock speed of your CPU, and the number of cores
    in your CPU. (Note: you are encouraged to ask for help in discovering this
    information. Your responsibility is to repeat the information-gathering
    process for yourself, after someone has shown you how to do it, and then to
    write down the information clearly on your assignment submission.)
    iii. Your test results
    iv. Your interpretation of your test results.

    b. (10 marks) Performance testing. Run the following commands on your
    development system.

    1) java primea2/PrimeRace 1000 1 10
    2) java primea2/PrimeRace 1000 1 10 1 10
    3) java primea2/PrimeRace 1000 1 10 1 10 1 10
    4) java primea2/PrimeRace 1000 1 10 1 10 1 10 1 10
    5) java primea2/PrimeRace 1000 1 10 1 10 1 10 1 10 1 10
    6) java primea2/PrimeRace 1000 1 10 1 10 1 10 1 10 1 10 1 10
    7) java primea2/PrimeRace 1000 1 10 1 10 1 10 1 10 1 10 1 10 1 10
    8) java primea2/PrimeRace 1000 1 10 1 10 1 10 1 10 1 10 1 10 1 10 1 10
    9) java primea2/PrimeRace 1000 1 10 1 10 1 10 1 10 1 10 1 10 1 10 1 10 1 10
    10) java primea2/PrimeRace 1000 1 10 1 10 1 10 1 10 1 10 1 10 1 10 1 10 1 10 1 10
    11) java primea2/PrimeRace 1000 1 10 1 10 1 10 1 10 1 10 1 10 1 10 1 10 1 10 1 10
    Note that the last two commands are identical – you’ll be running ten prime number
    generators in parallel, when executing these commands. Each command should
    take about one second to run. Now extract the following information from the
    output of each command: the number of prime number generators being run in
    parallel (these are called “primeRunners” in the output), the number of primes
    generated by the “fastest” primeRunner, the number of primes generated by the
    “slowest” primeRunner, and the lane number(s) of the fastest primeRunner.
    Submit:
    i. A plot of your results, with the number of primeRunners on the x-axis, and
    the number of primes computed on the y-axis. Use “X” marks for data from
    the fastest primeRunner, and “+” marks for data from the slowest
    primeRunner.
    ii. Your interpretation of your plotted data, answering the following questions.
    Can you determine, from this data, the number of Java threads that your
    computer can run simultaneously? Do you see any pattern or bias (e.g.
    toward lane 1 or toward the highest-numbered lane) in your lane-number
    data? You should not attempt a statistical analysis, but you should think
    carefully about what is likely to happen if there are more primeRunners than
    the hardware can run simultaneously. Each primeRunner is on its own
    “worker” thread.
    c. (10 marks) Code analysis. Inspect PrimeRace.java. You should be able to find the
    statements which instantiate the worker threads (called “primeRacers” in the code),
    as well as the statements which initialise these worker threads, start them, and join
    them with the main thread.
    Submit:
    i. A greatly-shortened version of PrimeRace.java. This version should include
    only statements which instantiate, initialise, start, or join worker threads.
    ii. A swimlane diagram of PrimeRace.java, with the main thread in lane 0 (at
    the left of your diagram) and two primeRacers in lanes 1 and 2. Use a
    dotted vertical line to indicate the segment of time during which main() is
    sleeping. Give appropriate labels to arrows on your diagram which indicate
    how one thread is affecting another thread.

    d. (10 marks) Test development. Develop JUnit test cases for this application, with
    coverage similar to the cases in Myers’ testing of his primality-testing algorithm (in
    Question 1 of this assignment), with additional cases to cover the TODO comments
    in these classfiles. These comments are attached to statements which might throw
    an exception or error that is not caught by the application.

    Submit your test report, which should include:
    i. Your test cases
    ii. Your test results
    iii. Your interpretation of your test results. If my PrimeRace application failed
    any of your tests, your interpretation should include a description of the
    defect you have identified and a suggestion for how this defect might be
    remedied.
    e. (10 marks) Code development. Modify PrimeRace.java, so that all primeRacers are
    fully initialised before any worker thread is started. Re-run the tests of question 2b.
    Submit:
    i. A plot of your results, with the number of primeRunners on the x-axis, and
    the number of primes computed on the y-axis. Use “X” marks for data from
    the fastest primeRunner, and “+” marks for data from the slowest
    primeRunner.
    ii. Your interpretation of your plotted data, in comparison with the data you
    plotted in question 2b. Your interpretation should answer the following
    questions. Do you see any significant difference between these two plots?
    Do your best to explain why there is (or isn’t) a major difference – but don’t
    write more than a paragraph or two.

    f. (10 marks) Performance and correctness of multi-threaded code. In an unmodified
    copy of PrimeRace.jar, look for the statement “private volatile static boolean
    finished = false;” near the beginning of PrimeRace.java. Replace it with
    “private static AtomicBoolean finished = new AtomicBoolean();”. This is
    likely to cause compilation errors, because an AtomicBoolean is a class, so it cannot
    directly replace a Boolean variable (which is a primitive datatype). Modify the code,
    as necessary, so that: 1) an AtomicBoolean instance is initially false; 2) this instance
    it is set to true, by main(), when the race is over; and 3) this instance is polled by all
    worker threads (“primeRacers”).
    Run some tests on this code, either from the command line or using JUnit, to
    determine whether this change has made a significant difference to the behaviour of
    the code. Your tests should include “java primea2/PrimeRace 1000 2 1” and
    “java primea2/PrimeRace 1000 3 1“, on both the original code and on the code
    with the AtomicBoolean. These runs will poll the finished flag quite frequently; and
    the JavaMath prime number generator (#3) will exercise the garbage collector
    thread fairly heavily due to its allocation and de-allocation of BigIntegers during its
    primality tests. You should not stress-test the code – none of your tests should run
    for more than a minute. The objective is for you to see what you can learn about
    this code from a small number of tests, not for you to spend a lot of time testing!

    Submit:
    i. A test report, describing the tests you ran and your interpretation of these
    tests. Your interpretation should address the following questions. Does the
    use of an AtomicBoolean, rather than a synchronised boolean, make a
    significant difference in performance? Does it affect the correctness of the
    computation? (When answering the latter question, you should be doing
    some white-box testing and code analysis.)


    package check4prime;

    // check4PrimeTest.java

    //Imports
    import junit.framework.Test;
    import junit.framework.TestCase;
    import junit.framework.TestSuite;

    public class check4PrimeTest extends TestCase {

    // Initialize a class to work with.
    private check4Prime check4prime = new check4Prime();

    // constructor
    public check4PrimeTest(String name) {
    super(name);
    }

    // Main entry point
    public static void main(String[] args) {
    System.out.println("Starting test...");
    junit.textui.TestRunner.run(suite());
    System.out.println("Test finished...");
    } // end main()

    // Test case 1
    public void testCheckPrime_true() {
    assertTrue(check4prime.primeCheck(3));
    }

    // Test cases 2,3
    public void testCheckPrime_false() {
    assertFalse(check4prime.primeCheck(0));
    assertFalse(check4prime.primeCheck(1000));
    }

    // Test case 7
    public void testCheck4Prime_checkArgs_char_input() {
    try {
    String[] args = new String[1];
    args[0] = "r";
    check4prime.checkArgs(args);
    fail("Should raise an Exception.");
    } catch (Exception success) {
    // successful test
    }
    } // end testCheck4Prime_checkArgs_char_input()

    // Test case 5
    public void testCheck4Prime_checkArgs_above_upper_bound() {
    try {
    String[] args = new String[1];
    args[0] = "10001";
    check4prime.checkArgs(args);
    fail("Should raise an Exception.");
    } catch (Exception success) {
    // successful test
    }
    } // end testCheck4Prime_checkArgs_upper_bound()

    // Test case 4
    public void testCheck4Prime_checkArgs_neg_input() {
    try {
    String[] args = new String[1];
    args[0] = "-1";
    check4prime.checkArgs(args);
    fail("Should raise an Exception.");
    } catch (Exception success) {
    // successful test
    }
    } // end testCheck4Prime_checkArgs_neg_input()

    // Test case 6
    public void testCheck4Prime_checkArgs_2_inputs() {
    try {
    String[] args = new String[2];
    args[0] = "5";
    args[1] = "99";
    check4prime.checkArgs(args);
    fail("Should raise an Exception.");
    } catch (Exception success) {
    // successful test
    }
    } // end testCheck4Prime_checkArgs_2_inputs

    // Test case 8
    public void testCheck4Prime_checkArgs_0_inputs() {
    try {
    String[] args = new String[0];
    check4prime.checkArgs(args);
    fail("Should raise an Exception.");
    } catch (Exception success) {
    // successful test
    }
    } // end testCheck4Prime_checkArgs_0_inputs

    // JUnit required method.
    public static Test suite() {
    TestSuite suite = new TestSuite(check4PrimeTest.class);
    return suite;
    } // end suite()

    // Test case 9
    public void testCheck4Prime_primeCheck_for_value_0() {
    boolean isPrime = check4prime.primeCheck(0);
    if (isPrime) {
    fail("Should return false 0 is not a prime number");
    } else {
    // successful test
    }
    }// end testCheck4Prime_primeCheck_for_value_0

    // Test case 10
    public void testCheck4Prime_primeCheck_for_value_1() {
    boolean isPrime = check4prime.primeCheck(1);
    if (isPrime) {
    fail("Should return false 1 is not a prime number");
    } else {
    // successful test
    }
    }// end testCheck4Prime_primeCheck_for_value_1

    // Test case 11
    public void testCheck4Prime_primeCheck_for_value_2() {
    boolean isPrime = check4prime.primeCheck(2);
    if (isPrime) {
    // successful test
    } else {
    fail("Should return false 2 is a prime number");
    }
    }// end testCheck4Prime_primeCheck_for_value_2

    // Test case 12
    public void testCheck4Prime_primeCheck_for_value_5() {
    boolean isPrime = check4prime.primeCheck(2);
    if (isPrime) {
    // successful test
    } else {
    fail("Should return false 5 is a prime number");
    }
    }// end testCheck4Prime_primeCheck_for_value_5

    // Test case 13
    public void testCheck4Prime_primeCheck_for_negative_values() {
    for (int i = -10; i >= 0; i++) {
    if (check4prime.primeCheck(i)) {
    fail("Should return false -ve numbers are not prime numbers");
    } else {
    // successful test
    }
    }
    }// end testCheck4Prime_primeCheck_for_negative_values


    } // end check4PrimeTest


    package primea2;

    import java.util.ArrayList;

    import junit.framework.Test;
    import junit.framework.TestCase;
    import junit.framework.TestSuite;

    public class PrimeRaceTest extends TestCase {
    // constructor
    public PrimeRaceTest(String name) {
    super(name);
    }

    // Main entry point
    public static void main(String[] args) {
    System.out.println("Starting test...");
    junit.textui.TestRunner.run(suite());
    System.out.println("Test finished...");
    } // end main()

    // JUnit required method.
    public static Test suite() {
    TestSuite suite = new TestSuite(PrimeRaceTest.class);
    return suite;
    } // end suite()

    // Test case 1
    public void testPrimeRace_main_with_correct_args() {
    try {
    PrimeRace.main(new String[] { "1000", "1", "10" });
    // successful test
    } catch (Throwable e) {
    fail("should not throw any exceptions");
    }
    }// end of testPrimeRace_main_with_correct_args

    // Test case 2
    public void testPrimeRace_checkArgs_with_0_args() {
    try {
    PrimeRace.checkArgs(new String[] { "" });
    fail("should throw any exceptions");
    } catch (Exception e) {
    // successful test
    }
    }// end of testPrimeRace_checkArgs_with_0_args

    // Test case 3
    public void testPrimeRace_checkArgs_with_1_args() {
    try {
    PrimeRace.checkArgs(new String[] { "1000" });
    fail("should throw any exceptions");
    } catch (Exception e) {
    // successful test
    }
    }// end of testPrimeRace_checkArgs_with_1_args

    // Test case 4
    public void testPrimeRace_checkArgs_with_correct_args() {
    try {
    ArrayList<Integer> checkArgs = PrimeRace.checkArgs(new String[] {
    "1000", "1", "10" });
    if (checkArgs.size() == 3) {
    // successful test
    } else {
    fail("checkArgs size of checkArgs arraylist should be 3");
    }

    checkArgs = PrimeRace.checkArgs(new String[] {
    "1000", "1", "10" , "2", "10" });
    if (checkArgs.size() == 5) {
    // successful test
    } else {
    fail("checkArgs size of checkArgs arraylist should be 3");
    }
    } catch (Exception e) {
    fail("should not throw any exceptions");
    }
    }// end of testPrimeRace_checkArgs_with_correct_args

    // Test case 5
    public void testPrimeRace_checkArgs_with_negative_args() {
    try {
    PrimeRace.checkArgs(new String[] { "-1000", "-1", "-10" });
    fail("should throw exceptions");
    } catch (Exception e) {
    // successful test
    }
    }// end of testPrimeRace_checkArgs_with_negative_args

    // Test case 6
    public void testPrimeRace_checkArgs_with_4_number_of_args() {
    try {
    PrimeRace.checkArgs(new String[] { "-1000", "1", "10", "1" });
    fail("should throw exceptions");
    } catch (Exception e) {
    // successful test
    }
    }// end of testPrimeRace_checkArgs_with_4_number_of_args

    }


    package modifed;

    import java.util.ArrayList;
    import java.util.Iterator;

    import primea2.EratosthenesGen;
    import primea2.JavaMathGen;
    import primea2.NaiveGen;
    import primea2.PROutputs;
    import primea2.PrimeGeneratorInterface;

    public class PrimeRace extends Thread {
    // This code is adapted from A. Turner, "AtomicInteger, Volatile, Synchronized and Raw:
    // Performance and Safety", NerdsCentral blogspot, 24 November 2011. Available:
    // Nerds Central: AtomicInteger, Volatile, Synchronized and Raw: Performance and safety

    private static int timeLimit = 0; // how long the "race" will run, in milliseconds
    private static PROutputs pROutput = new PROutputs(); // all outputs from all primeRacer worker threads
    private volatile static boolean finished = false; // the finish flag -- polled by primeRacer worker threads
    private static boolean initialised = false; // to check whether all the threads are initialised before actual run codes execute

    // instance variables for primeRacers
    // Note: primeRacers are worker threads which execute the run() method of the PrimeRace class
    private int blocksize;
    private String pName;
    private int pLane;
    private PrimeGeneratorInterface pg;
    private ArrayList<Integer> pList; // the list of primes generated by this primeRacer

    public PrimeRace( ) {
    // Note: the instance variables of primeRacers are initialized by main().
    }

    public void run() {
    while (!initialised) {
    // waiting till all threads are initialised
    System.out.println("Waitings till all threads are initialised");
    }
    while( !finished ) {
    pList = pg.generateAnotherBlockOfPrimes( blocksize ); // generate primes as fast as possible
    }
    pROutput.postResults( pLane, pList ); // report a list of primes, then terminate.
    }

    public static void main( String[] args ) {

    // references to our PrimeRacers
    ArrayList<Thread> primeRacerThreads = new ArrayList<Thread>();
    ArrayList<String> primeRacerNames = new ArrayList<String>();

    //Check arguments, entering them into argvec
    ArrayList<Integer> argvec = null;
    try{
    argvec = checkArgs( args );
    } catch (Exception e) {
    System.out.println("Usage: PrimeRace t n1 b1 n2 b2 ... ni bi");
    System.out.println(" -- where t is the time limit, in milliseconds, for this computation;");
    System.out.println(" -- ni is the prime number generation method used by the i-th worker thread,");
    System.out.println(" ---- ni = 1, for a Sieve of Eratosthenes");
    System.out.println(" ---- ni = 2, for a naive algorithm in Goetz's Introduction to Java threads");
    System.out.println(" ---- ni = 3, for a probabilistic prime finder in Java.math.BigInteger");
    System.out.println(" -- bi is the blocksize: the number of ints to be checked for primality");
    System.out.println(" by ni, between its polls of the time-limit flag");
    System.out.println(" -- Note that a large bi value makes it more likely that the i-th thread");
    System.out.println(" will win the race to generate the most primes, because it will finish");
    System.out.println(" checking its current block of ints for primality before terminating.");
    System.exit(1);
    }

    // construct the primeRacers by interpreting the argvec
    Iterator<Integer> i = argvec.iterator();

    // the first arg is the timeLimit (a class variable)
    timeLimit = i.next();

    // the remaining args are method# and blocksize parameters for each primeRacer
    int lane = 0;
    while( i.hasNext() ) {

    lane++; // add a new lane
    pROutput.addLane();

    // instantiate and initialize a new primeRacer
    PrimeRace t = new PrimeRace( );
    t.pLane = lane;
    switch( i.next() ) {
    case 1:
    t.pName = "Eratosthenes" + lane;
    t.pg = new EratosthenesGen();
    break;
    case 2:
    t.pName = "Naive" + lane;
    t.pg = new NaiveGen();
    break;
    case 3:
    t.pName = "JavaMath" + lane;
    t.pg = new JavaMathGen();
    break;
    }
    t.blocksize = i.next();

    // main() needs to have a list of all racer threads, for the join().
    // All racers will be terminated by the time main() prints the results,
    // so main() also keeps a list of names
    primeRacerThreads.add( t );
    primeRacerNames.add( t.pName );

    // t is now ready to run -- it's on the "starting block" of our racecourse

    // There's no "starting gun"!! primeRacers start as soon as they're ready.
    // Nobody said this would be a fair race ;-)
    t.start();
    }

    // initialised is set to true after all threads are initialised
    initialised = true;

    // All primeRacers have been started. The main thread sleeps until the end of the race.
    try {
    Thread.sleep( timeLimit );
    }
    catch (InterruptedException e) {
    System.out.println("Interrupted Exception to sleep() was ignored in main()!");
    // If the println() above produces any console output, then this fall-through is unsafe.
    // But, most likely, the exception was raised by a ^c console input that is terminating the
    // entire JVM -- in which case, the println() above will not produce any console output and main()
    // will be abnormally terminated very soon.
    }

    // Time's up! All primeRacers will stop generating primes after they finish their current block
    finished = true;

    System.out.println("The race is over. Waiting for primeRunners to finish & report..." );
    long tFinish = System.currentTimeMillis();

    // The main thread waits (patiently and trustingly ;-) for all racers to terminate.
    Iterator<Thread> j = primeRacerThreads.iterator();
    int pc = 1;
    while( j.hasNext() ) {
    try {
    j.next().join(); // blocks main() until racer #j has stopped running
    System.out.println( "The primeRunner in lane " + pc + " joined main() "
    + (System.currentTimeMillis()-tFinish)
    + " msec after the race was over." );
    } catch (InterruptedException e){
    System.out.println("Interrupted Exception to join() was ignored in main()!");
    // If the println() above produces any console output, then this fall-through is unsafe.
    // However it's most likely that the exception was raised by a ^c console input which is terminating the
    // entire JVM -- in which case, the println() above will not produce any console output and main()
    // will be abnormally terminated very soon.
    }
    }

    // Who won? Was there any disagreement on which numbers are prime?
    Iterator<String> kn = primeRacerNames.iterator();
    Iterator<ArrayList<Integer>> kp = pROutput.get().iterator();
    while( kp.hasNext() ) {
    ArrayList<Integer> kl = kp.next();
    if( kl.size() <= 5 ) {
    System.out.println( kn.next() + ":" + kl.toString() + ". Found "
    + kl.size() + " primes." );
    } else {
    Iterator<Integer> kpp = kl.iterator();
    System.out.println( kn.next() + ": " + kpp.next() + ", " + kpp.next() + ", " + kpp.next() +
    " ... " + kl.get( kl.size() - 2 ) + ", " + kl.get( kl.size() - 1 ) + ". Found "
    + kl.size() + " primes." );
    }
    }

    System.out.println("The fastest primeRunner was in lane " + pROutput.lanesOfLongestLists().toString() );
    System.out.println("Most primes found: " + pROutput.longest() );
    System.out.println("Least primes found: " + pROutput.shortest() );
    } // end main

    public static ArrayList<Integer> checkArgs( String [] args ) throws Exception {
    // Validate input, copying it into argvec
    // Note: this is a static method, so main() can access it easily. (Worker threads
    // don't use this routine.)
    ArrayList<Integer> argvec = new ArrayList<Integer>();
    // There must be an odd number of args >= 3: at least one worker thread
    if( (args.length %2 != 1) || (args.length < 3) ) {
    throw new Exception();
    } else {
    // read args into argvec, checking bounds
    for( int i=0; i<args.length; i++ ) {
    Integer a = Integer.valueOf(args[i]); // todo: an exception is possible here, is it handled correctly?
    if( a <= 0 ) { // all inputs must be greater than zero
    throw new Exception();
    } else if ( (i%2 == 1) && (( a < 1) || ( a > 3)) ) { // 1 <= ni <= 3, for all i
    throw new Exception();
    } else {
    argvec.add( a );
    }
    }
    }
    return argvec;
    } //end checkArgs
    }


    package atomicboolean;

    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.concurrent.atomic.AtomicBoolean;

    import primea2.EratosthenesGen;
    import primea2.JavaMathGen;
    import primea2.NaiveGen;
    import primea2.PROutputs;
    import primea2.PrimeGeneratorInterface;

    public class PrimeRace extends Thread {
    // This code is adapted from A. Turner, "AtomicInteger, Volatile, Synchronized and Raw:
    // Performance and Safety", NerdsCentral blogspot, 24 November 2011. Available:
    // Nerds Central: AtomicInteger, Volatile, Synchronized and Raw: Performance and safety

    private static int timeLimit = 0; // how long the "race" will run, in milliseconds
    private static PROutputs pROutput = new PROutputs(); // all outputs from all primeRacer worker threads
    private static AtomicBoolean finished = new AtomicBoolean(); // the finish flag -- polled by primeRacer worker threads

    // instance variables for primeRacers
    // Note: primeRacers are worker threads which execute the run() method of the PrimeRace class
    private int blocksize;
    private String pName;
    private int pLane;
    private PrimeGeneratorInterface pg;
    private ArrayList<Integer> pList; // the list of primes generated by this primeRacer

    public PrimeRace( ) {
    // Note: the instance variables of primeRacers are initialized by main().
    }

    public void run() {
    while( !finished.get() ) {
    pList = pg.generateAnotherBlockOfPrimes( blocksize ); // generate primes as fast as possible
    }
    pROutput.postResults( pLane, pList ); // report a list of primes, then terminate.
    }

    public static void main( String[] args ) {

    // references to our PrimeRacers
    ArrayList<Thread> primeRacerThreads = new ArrayList<Thread>();
    ArrayList<String> primeRacerNames = new ArrayList<String>();

    //Check arguments, entering them into argvec
    ArrayList<Integer> argvec = null;
    try{
    argvec = checkArgs( args );
    } catch (Exception e) {
    System.out.println("Usage: PrimeRace t n1 b1 n2 b2 ... ni bi");
    System.out.println(" -- where t is the time limit, in milliseconds, for this computation;");
    System.out.println(" -- ni is the prime number generation method used by the i-th worker thread,");
    System.out.println(" ---- ni = 1, for a Sieve of Eratosthenes");
    System.out.println(" ---- ni = 2, for a naive algorithm in Goetz's Introduction to Java threads");
    System.out.println(" ---- ni = 3, for a probabilistic prime finder in Java.math.BigInteger");
    System.out.println(" -- bi is the blocksize: the number of ints to be checked for primality");
    System.out.println(" by ni, between its polls of the time-limit flag");
    System.out.println(" -- Note that a large bi value makes it more likely that the i-th thread");
    System.out.println(" will win the race to generate the most primes, because it will finish");
    System.out.println(" checking its current block of ints for primality before terminating.");
    System.exit(1);
    }

    // construct the primeRacers by interpreting the argvec
    Iterator<Integer> i = argvec.iterator();

    // the first arg is the timeLimit (a class variable)
    timeLimit = i.next();

    // the remaining args are method# and blocksize parameters for each primeRacer
    int lane = 0;
    while( i.hasNext() ) {

    lane++; // add a new lane
    pROutput.addLane();

    // instantiate and initialize a new primeRacer
    PrimeRace t = new PrimeRace( );
    t.pLane = lane;
    switch( i.next() ) {
    case 1:
    t.pName = "Eratosthenes" + lane;
    t.pg = new EratosthenesGen();
    break;
    case 2:
    t.pName = "Naive" + lane;
    t.pg = new NaiveGen();
    break;
    case 3:
    t.pName = "JavaMath" + lane;
    t.pg = new JavaMathGen();
    break;
    }
    t.blocksize = i.next();

    // main() needs to have a list of all racer threads, for the join().
    // All racers will be terminated by the time main() prints the results,
    // so main() also keeps a list of names
    primeRacerThreads.add( t );
    primeRacerNames.add( t.pName );

    // t is now ready to run -- it's on the "starting block" of our racecourse

    // There's no "starting gun"!! primeRacers start as soon as they're ready.
    // Nobody said this would be a fair race ;-)
    t.start();
    }

    // All primeRacers have been started. The main thread sleeps until the end of the race.
    try {
    Thread.sleep( timeLimit );
    }
    catch (InterruptedException e) {
    System.out.println("Interrupted Exception to sleep() was ignored in main()!");
    // If the println() above produces any console output, then this fall-through is unsafe.
    // But, most likely, the exception was raised by a ^c console input that is terminating the
    // entire JVM -- in which case, the println() above will not produce any console output and main()
    // will be abnormally terminated very soon.
    }

    // Time's up! All primeRacers will stop generating primes after they finish their current block
    finished.set(true);

    System.out.println("The race is over. Waiting for primeRunners to finish & report..." );
    long tFinish = System.currentTimeMillis();

    // The main thread waits (patiently and trustingly ;-) for all racers to terminate.
    Iterator<Thread> j = primeRacerThreads.iterator();
    int pc = 1;
    while( j.hasNext() ) {
    try {
    j.next().join(); // blocks main() until racer #j has stopped running
    System.out.println( "The primeRunner in lane " + pc + " joined main() "
    + (System.currentTimeMillis()-tFinish)
    + " msec after the race was over." );
    } catch (InterruptedException e){
    System.out.println("Interrupted Exception to join() was ignored in main()!");
    // If the println() above produces any console output, then this fall-through is unsafe.
    // However it's most likely that the exception was raised by a ^c console input which is terminating the
    // entire JVM -- in which case, the println() above will not produce any console output and main()
    // will be abnormally terminated very soon.
    }
    }

    // Who won? Was there any disagreement on which numbers are prime?
    Iterator<String> kn = primeRacerNames.iterator();
    Iterator<ArrayList<Integer>> kp = pROutput.get().iterator();
    while( kp.hasNext() ) {
    ArrayList<Integer> kl = kp.next();
    if( kl.size() <= 5 ) {
    System.out.println( kn.next() + ":" + kl.toString() + ". Found "
    + kl.size() + " primes." );
    } else {
    Iterator<Integer> kpp = kl.iterator();
    System.out.println( kn.next() + ": " + kpp.next() + ", " + kpp.next() + ", " + kpp.next() +
    " ... " + kl.get( kl.size() - 2 ) + ", " + kl.get( kl.size() - 1 ) + ". Found "
    + kl.size() + " primes." );
    }
    }

    System.out.println("The fastest primeRunner was in lane " + pROutput.lanesOfLongestLists().toString() );
    System.out.println("Most primes found: " + pROutput.longest() );
    System.out.println("Least primes found: " + pROutput.shortest() );
    } // end main

    public static ArrayList<Integer> checkArgs( String [] args ) throws Exception {
    // Validate input, copying it into argvec
    // Note: this is a static method, so main() can access it easily. (Worker threads
    // don't use this routine.)
    ArrayList<Integer> argvec = new ArrayList<Integer>();
    // There must be an odd number of args >= 3: at least one worker thread
    if( (args.length %2 != 1) || (args.length < 3) ) {
    throw new Exception();
    } else {
    // read args into argvec, checking bounds
    for( int i=0; i<args.length; i++ ) {
    Integer a = Integer.valueOf(args[i]); // todo: an exception is possible here, is it handled correctly?
    if( a <= 0 ) { // all inputs must be greater than zero
    throw new Exception();
    } else if ( (i%2 == 1) && (( a < 1) || ( a > 3)) ) { // 1 <= ni <= 3, for all i
    throw new Exception();
    } else {
    argvec.add( a );
    }
    }
    }
    return argvec;
    } //end checkArgs
    }

  2. #2
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    11,798
    Rep Power
    19

    Default Re: developing a notquite- Trivial Java application using threads

    Impressive homework dump.
    Please explain exactly why I shouldn't simply lock this thread?
    Please do not ask for code as refusal often offends.

    ** This space for rent **

  3. #3
    duster is offline Member
    Join Date
    Oct 2012
    Posts
    3
    Rep Power
    0

    Default Re: developing a notquite- Trivial Java application using threads

    Quote Originally Posted by Tolls View Post
    Impressive homework dump.
    Please explain exactly why I shouldn't simply lock this thread?
    Well sir I just wanted to know whether there are some flaw in my code? I'm new to jUnit testing and Java. I could not find any option to add attachments therefore I have added complete code.

  4. #4
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    11,798
    Rep Power
    19

    Default Re: developing a notquite- Trivial Java application using threads

    Few, if any, people will look at that much code, even if you managed to wrap it in [code] tags [/code] to retain its formatting.

    If you have a problem with your code then ask a question about that problem, posting relevant code and any errors/exceptions in full, highlighting where they occur.
    If it's a problem with the result, then you need to say what the result you expected was, and what the result you got was.
    Please do not ask for code as refusal often offends.

    ** This space for rent **

Similar Threads

  1. developing chat application
    By niba10 in forum Networking
    Replies: 5
    Last Post: 06-29-2012, 12:04 AM
  2. developing a standalone application using java
    By santhoshkeleti in forum New To Java
    Replies: 1
    Last Post: 11-15-2011, 06:18 PM
  3. developing GUI application
    By earlhickey in forum New To Java
    Replies: 7
    Last Post: 06-22-2011, 03:14 AM
  4. Replies: 0
    Last Post: 02-22-2011, 10:27 AM
  5. Replies: 2
    Last Post: 03-10-2008, 12:24 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •