Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - Call to start method on thread : how does it route to Runnable interface's run ()?

Ok , I know the two standard ways to create a new thread and run it in Java :

  1. Implement Runnable in a class, define run() method, and pass an instance of the class to a new Thread. When the start() method on the thread instance is called, the run method of the class instance will be invoked.

  2. Let the class derive from Thread, so it can to override the method run() and then when a new instance's start() method is called, the call is routed to overridden method.

In both methods, basically a new Thread object is created and its start method invoked. However, while in the second method, the mechanism of the call being routed to the user defined run() method is very clear, (it's a simple runtime polymorphism in play), I don't understand how the call to start() method on the Thread object gets routed to run() method of the class implementing Runnable interface. Does the Thread class have an private field of Type Runnable which it checks first, and if it is set then invokes the run method if it set to an object? that would be a strange mechanism IMO.

How does the call to start() on a thread get routed to the run method of the Runnable interface implemented by the class whose object is passed as a parameter when constructing the thread?

like image 884
Bhaskar Avatar asked Apr 07 '10 22:04

Bhaskar


4 Answers

The Thread keeps a reference to the Runnable instance, and calls it in the base implementation of run.

You can see this in the source:

// passed into the constructor and set in the init() method
private Runnable target;
...
// called from native thread code after start() is called
public void run() {
    if (target != null) {
        target.run();
    }
}
like image 128
SLaks Avatar answered Sep 29 '22 08:09

SLaks


While you can look at the actual source code, at a guess it would be something like:

public class MyThread implements Runnable {
 private  Runnable r;
 public MyThread() {
 }
 public MyThread(Runnable r) {
        this.r = r;
 }

 public void start() {
   //magic to launch a new thread
   run(); // the above magic would probably call run(), rather than
          // call it directly here though.
  }
  public void run() {
    if(r != null) 
       r.run();
   }
}

In short, if you extend MyThread and override run(), your run() method would be called. If you passed a Runnable instead, the run() method of MyThread would just delegate to the run() method of that Runnable.

like image 20
nos Avatar answered Sep 29 '22 07:09

nos


In both the cases there has to be concrete Thread class. In the first case (implementing a Runnable), makes the class that implements it capable of 'being' a thread. You still have to pass your class as an argument to the constructor of the Thread class. Whereas thats not the scenario in the second case where you extend a Thread Class.

When a start() method is called, there is no guarantee that the run() method will be immediately invoked. Calling a start() method tells that the thread is ready to run. It can go to any of the states thereafter depending on the Thread pooler.

FYI : class Thread implements Runnable

like image 30
bragboy Avatar answered Sep 29 '22 09:09

bragboy


You could have just checked the source of Thread.java included as part of the JDK:

public void run() {
    if (target != null) {
        target.run();
    }
}

where target is:

private Runnable target;

But I think the real answer you are looking for is the details on how threads really work. That is unfortunately abstracted away in native libraries. Just try to get a high level understanding of how threading works.

like image 22
Pyrolistical Avatar answered Sep 29 '22 07:09

Pyrolistical