3

I am trying to understand below program. If I call new ReaderThread().start() it is working fine, but if I call new ReaderThread().run(), the application goes into an infinite loop. What is the difference?

public class Contention {

    private static boolean ready;
    private static int number;

    private static class ReaderThread extends Thread {
        public void run() {
                 while (!ready){
                System.out.println("ready ..."+ready);
                Thread.yield();}
            System.out.println(number);
           // }
        }
    }


    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new ReaderThread().run();
        number = 42;
        ready = true;

    }

}
Thomas Owens
  • 114,398
  • 98
  • 311
  • 431
Raj
  • 75
  • 1
  • 1
  • 9
  • Check the answer here: http://stackoverflow.com/questions/3027495/java-thread-run-and-start-methods – BenCole Sep 08 '11 at 13:45

6 Answers6

11

when you call run() you do so in the same thread. Its just a method call.

When you call start() to a triggering another Thread to call run()

This is one of the reasons its not a good idea to extend Thread, but instead implement Runnable which you wrap with a thread. This is one of the many potential sources of confusion.


Here is a related teaser for you

static String name = "Peter Lawrey";
static String state = "Washington";

static String getName() {
  return name;
}

static String getState() {
  return state;
}

static class NamedThread extends Thread {
  @Override
  public void run() {
    System.out.println(getName()+" - "+getState());
  }
}

public static void main(String... args) throws InterruptedException {
  new NamedThread().start();
}

prints

Thread-0 - RUNNABLE

Can you work out why?

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • I am not sure Peter,Could you please explain to me. – Raj Sep 08 '11 at 14:08
  • I execute above code,by implementing runnable and using run method it displaying correct name,But by extending Thread class and using start() method it displaying as Thread-0-RUNNABLE.Could you please explain what is happening here. – Raj Sep 08 '11 at 14:13
  • 1
    I got it,getName() and getState() are the methods of thread class. – Raj Sep 08 '11 at 14:38
4

run() is just a method which won't start a new thread - so main() will never get to set ready to true.

Only start() will actually spawn a separate thread of execution - which is what you need.

Note that even with this, your code isn't guaranteed to work due to memory model concerns - you need to worry about the visibility of the changes you make to shared data.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
2

Read carefully about threads in java (for example http://download.oracle.com/javase/tutorial/essential/concurrency/)

When you call method run(), you call it just as any other method and it will work in the same thread as calling method.

Illarion Kovalchuk
  • 5,774
  • 8
  • 42
  • 54
2

If you use new ReaderThread().start();,you are creating actually a new thread instance which will run in the background and main() resumes with its further execution.

But new ReaderThread().run(); creates an instance of this class and makes a normal method call to the run() method, so the main() has to wait till the run() has finished executing and returned the control back to main(), which in your case is an infinite loop.

If you want to start a new thread then start by using ReaderThread().start(); this is the correct way to start a thread, there are no alternatives for this.

Rakesh
  • 4,264
  • 4
  • 32
  • 58
1
public class Contention {

    private static boolean ready;
    private static int number;

    private static class ReaderThread extends Thread {
        public void run() {
                 while (!ready){
                System.out.println("ready ..."+ready);
                Thread.yield();}
            System.out.println(number);
           // }
        }
    }




    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new ReaderThread().run();//control goes to run() method

//and it keeps running and next line of code where you set ready=true will not be executed
        number = 42;
        ready = true;

    }

}

edited:

because Threads don't run together (but concurrently), but OS decides which one runs and it makes sure that every thread gets its own chance based on TimeShared basis (or any algorithm). so may be in your case the other thread gets chance first and it gets executed before main() thread gets a chance to run and set ready = true. but if you run your code again the other case is also possible. where ready = true; is set and Thread wont enter While() loop.

ngesh
  • 13,398
  • 4
  • 44
  • 60
  • Thanks,Suppose say i am using start() instead of run() ,So control going to ready=true;,But in while loop it should be always false,because there i am checking !ready.How control is going inside of while loop. – Raj Sep 08 '11 at 13:52
  • When you use "start" instead of "run", new thread gets started and yield gives chance for main thread to run and then main thread sets value of ready to true and when "new thread" gets chance to start running, it checks value and exits loop. – Delta Sep 08 '11 at 13:57
  • Use setPriority method and play with it by setting different priority. – Delta Sep 08 '11 at 14:00
  • So here two thread are running right one is main thread and other is ReaderThread(),So i am starting ReaderThread ,Reader thread setting ready to true,after entering while block,i am calling thread.yield(),As per yield ,Threadscheduler give up ReaderThread and should use main thread.So main thread printing value as 42 if i am correct? – Raj Sep 08 '11 at 14:02
  • comment out Thread.yield().. set priority and see what happens? :) – Delta Sep 08 '11 at 14:37
  • I am not seeing any difference Delta. – Raj Sep 08 '11 at 15:12
1

When you have new ReaderThread().run(); it's in the same thread and ready = true; never reached.

But when you call new ReaderThread().start() it starts a new thread and main thread also continue and will hit ready = true; - which will take the thread created out of the loop...

Prabath Siriwardena
  • 5,891
  • 1
  • 27
  • 34
  • 2
    When you use new ReaderThread().start() - its the ReaderThread which executes the while loop - when you use new ReaderThread().start() its the main thread... – Prabath Siriwardena Sep 08 '11 at 17:51