Member Avatar for Javam

Hey, Can you please give an solution of why this doesn't work correctly?

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 *
 */
public class Main
{
     static Thread hare = new Thread(new ThreadRunner("hare",90,100));
    static Thread tortoise = new Thread(new ThreadRunner("tortoise",0,10));
    
     public static void main(String[] args)
    {
        hare.start();
        tortoise.start();
    }
    public static void finished(Thread winner)
    {
        if(winner.equals(hare))
        {
            System.out.println("The race is over, hare wins");
            tortoise.interrupt();
    

        }
         if(winner.equals(tortoise))
        {
              System.out.println("The race is over, tortoise wins");
            hare.interrupt();
         
        }
    }

}
 class ThreadRunner implements Runnable {
    private String name;
    private int chance;
    private int speed;
    private int distance;

    
    public ThreadRunner(String name, int chance, int speed)
    {
        this.name = name;
        this.chance = chance;
        this.speed = speed;
    }

    public void run()  {
         int randomNo;
        while(distance!=1000)
        {
             randomNo = ((int) (Math.random() * 99)) + 1;
             if(chance<=randomNo)
             {
                 distance+=speed;
                 System.out.println(name+" : "+distance+" m");
            }
            try{
             Thread.sleep(100);
            }catch(InterruptedException e){
                System.out.println(name+": You won fare and square!");
             
            }
        }
         System.out.println(name + " :I finished");
          Main.finished(Thread.currentThread());
        

       
    }

}

My output is :
tortoise : 10 m
tortoise : 20 m
tortoise : 30 m
tortoise : 40 m
hare : 100 m
tortoise : 50 m
tortoise : 60 m
tortoise : 70 m
tortoise : 80 m
tortoise : 90 m
tortoise : 100 m
tortoise : 110 m
tortoise : 120 m
tortoise : 130 m
tortoise : 140 m
tortoise : 150 m
tortoise : 160 m
tortoise : 170 m
tortoise : 180 m
tortoise : 190 m
tortoise : 200 m
tortoise : 210 m
tortoise : 220 m
tortoise : 230 m
tortoise : 240 m
tortoise : 250 m
tortoise : 260 m
hare : 200 m
tortoise : 270 m
tortoise : 280 m
tortoise : 290 m
tortoise : 300 m
tortoise : 310 m
tortoise : 320 m
tortoise : 330 m
tortoise : 340 m
tortoise : 350 m
tortoise : 360 m
tortoise : 370 m
tortoise : 380 m
tortoise : 390 m
tortoise : 400 m
tortoise : 410 m
tortoise : 420 m
tortoise : 430 m
hare : 300 m
tortoise : 440 m
tortoise : 450 m
tortoise : 460 m
tortoise : 470 m
tortoise : 480 m
tortoise : 490 m
tortoise : 500 m
tortoise : 510 m
tortoise : 520 m
tortoise : 530 m
tortoise : 540 m
tortoise : 550 m
tortoise : 560 m
tortoise : 570 m
tortoise : 580 m
tortoise : 590 m
hare : 400 m
tortoise : 600 m
tortoise : 610 m
tortoise : 620 m
tortoise : 630 m
tortoise : 640 m
hare : 500 m
tortoise : 650 m
tortoise : 660 m
tortoise : 670 m
tortoise : 680 m
tortoise : 690 m
tortoise : 700 m
hare : 600 m
tortoise : 710 m
tortoise : 720 m
tortoise : 730 m
tortoise : 740 m
tortoise : 750 m
tortoise : 760 m
tortoise : 770 m
tortoise : 780 m
hare : 700 m
tortoise : 790 m
tortoise : 800 m
tortoise : 810 m
hare : 800 m
tortoise : 820 m
tortoise : 830 m
tortoise : 840 m
tortoise : 850 m
tortoise : 860 m
tortoise : 870 m
tortoise : 880 m
tortoise : 890 m
tortoise : 900 m
tortoise : 910 m
tortoise : 920 m
tortoise : 930 m
tortoise : 940 m
tortoise : 950 m
tortoise : 960 m
tortoise : 970 m
tortoise : 980 m
tortoise : 990 m
tortoise : 1000 m
tortoise :I finished
The race is over, tortoise wins
hare: You won fare and square!
hare : 900 m
hare : 1000 m
hare :I finished
The race is over, hare wins


As you see, it allows both threads to finish the loop. How Can I not allow this? (without using something like System.exit(0) when I catch interrupt). Thanks :)

Recommended Answers

All 5 Replies

Member Avatar for Javam

Ok, I solved this part using a simple static boolean.

But, I have another problem. How can I set this "race" to run more than once? If I put the hare.start() and tortoise.start() inside a loop, I get an exception thrown.

I followed this with the debugger and found

if (threadStatus != 0 || this != me)
            throw new IllegalThreadStateException();

this if condition is true, because once the loop runs once, threadStatus is 2. Can anyone explain this?

You are missing a `return` statement in your catch block:

try {
   Thread.sleep(100);
} catch(InterruptedException e) {
   // print win
    return;
}

Basically, when the 'loser' thread is interrupted by the main class, you catch the exception, log the message but continue with the loop and hence the program keeps going on.

Member Avatar for Javam

You are missing a `return` statement in your catch block:

try {
   Thread.sleep(100);
} catch(InterruptedException e) {
   // print win
    return;
}

Basically, when the 'loser' thread is interrupted by the main class, you catch the exception, log the message but continue with the loop and hence the program keeps going on.

ah yes, much more simple solution than a static boolean, thanks. I am not sure if you saw my latest post, but could you please take a look at that?

Sprinkling a lot of "static" constructs (variables/methods) throughout your code normally leads to hard to maintain code. Regarding the question of running the race multiple times, simply moving the Thread instantiation to the main() method and looping over it should do the job.

// untested
public static void main(final String[] args) {
  for(int i = 0; i < 10; ++i) {
    Thread hare = new Thread(/* */);
    Thread tortoise = new Thread(/* */);
    hare.start();
    tortoise.start();
    hare.join();
    tortoise.join();    
  }
}

The join() call ensures that new "races" are not started as long as a race is in progress.

BTW, I think that this design can be made much more simpler and logical. You can have a Racer class which has the attributes like speed, chance, name etc. Tortoise and Hare would be subclasses of this Racer class. Your ThreadRunner (better name would be RacingSimulator) would take a Racer along with a RaceCompletonHandler (which is basically a class with a single method finished()). So, the code would look something like this:

// untested
public class Main {

    public static void main(final String[] args) {
        RaceCompletionHandler handler = new RaceCompletionHandler();
        Hare h = new Hare();
        Tortoise t = new Tortoise();
        RacingSimulator simulatorHare = new RacingSimulator(h, handler);
        RacingSimulator simulatorTor = new RacingSimulator(t, handler);
        for(int i = 0; i < 10; ++i) {
            Thread hThread = new Thread(simulatorHare);
            Thread tThraed = new Thread(simulatorTor);
            
            // start threads
            hThread.start();
            tThread.start();

            // join them
            hThread.join();
            tThread.join();
        }
    }

}

class Racer() {
    // attributes
}
class Hare extends Racer {}
class Tortoise extends Racer {}
Member Avatar for Javam

Sprinkling a lot of "static" constructs (variables/methods) throughout your code normally leads to hard to maintain code. Regarding the question of running the race multiple times, simply moving the Thread instantiation to the main() method and looping over it should do the job.

// untested
public static void main(final String[] args) {
  for(int i = 0; i < 10; ++i) {
    Thread hare = new Thread(/* */);
    Thread tortoise = new Thread(/* */);
    hare.start();
    tortoise.start();
    hare.join();
    tortoise.join();    
  }
}

The join() call ensures that new "races" are not started as long as a race is in progress.

BTW, I think that this design can be made much more simpler and logical. You can have a Racer class which has the attributes like speed, chance, name etc. Tortoise and Hare would be subclasses of this Racer class. Your ThreadRunner (better name would be RacingSimulator) would take a Racer along with a RaceCompletonHandler (which is basically a class with a single method finished()). So, the code would look something like this:

// untested
public class Main {

    public static void main(final String[] args) {
        RaceCompletionHandler handler = new RaceCompletionHandler();
        Hare h = new Hare();
        Tortoise t = new Tortoise();
        RacingSimulator simulatorHare = new RacingSimulator(h, handler);
        RacingSimulator simulatorTor = new RacingSimulator(t, handler);
        for(int i = 0; i < 10; ++i) {
            Thread hThread = new Thread(simulatorHare);
            Thread tThraed = new Thread(simulatorTor);
            
            // start threads
            hThread.start();
            tThread.start();

            // join them
            hThread.join();
            tThread.join();
        }
    }

}

class Racer() {
    // attributes
}
class Hare extends Racer {}
class Tortoise extends Racer {}

The reason for the static variables etc is because I was just trying to get a basic understanding of how threads execute, and therefore just hacked together the simplest method of doing that.
Thanks very much for your time.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.