Reputation: 7523
Ok , I know the two standard ways to create a new thread and run it in Java :
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.
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?
Upvotes: 6
Views: 6099
Reputation: 887315
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();
}
}
Upvotes: 7
Reputation: 137567
The one thing that's not yet been explored by the answers is how things get from start()
to run()
, which is simultaneously both simple and complex.
In simplistic terms, the start()
method calls a native method (start0
in the OpenJDK implementation) which allocates some memory for a new stack and asks the OS to run a thread with that space as stack and with a plain C++ function (thread_entry
in the OpenJDK implementation) as implementation function. That function in turn does the thunk back into Java to call the run()
method on the Thread object. The pattern at the low level (asking the OS to start a new thread on a stack and with a function) should be familiar to anyone doing native threads in either POSIX systems or Windows.
The detail makes it all a lot more complex, with all the error handling and obscure edge cases that need to be handled. If you're curious, read the OpenJDK sources, paying particular attention to Thread.java
, JVM_StartThread
in jvm.cpp
and the JavaThread
class in thread.cpp
and thread.hpp
. Hopefully this answer gives you enough detail for you to find your own way...
Upvotes: 1
Reputation: 229058
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.
Upvotes: 2
Reputation: 28062
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.
Upvotes: 1
Reputation: 35542
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
Upvotes: 1