Reputation: 85
can someone explain me why output after execution this program is so different?
First of all, classes: Thread extending java.lang.Thread
public class UsingThreadExtension extends Thread {
public UsingThreadExtension(String s) {
super(s);
}
@Override
public void run() {
for (int i=0; i<5; i++) {
System.out.println(i + " " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Implementation of java.lang.Runnable:
public class UsingRunnableImplementation implements Runnable {
@Override
public void run() {
for (int i=0; i<5; i++) {
System.out.println(i + " " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
And main class:
public class ThreadsExample {
public static void main(String[] args) {
UsingThreadExtension threadA = new UsingThreadExtension("Thread A");
UsingRunnableImplementation runnableImplementation = new UsingRunnableImplementation();
Thread threadB = new Thread(runnableImplementation, "Thread B");
//threadA.start();
threadB.start();
try {
//threadA.join();
threadB.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
//threadA.run();
threadB.run();
System.out.println("Main thread says hello!");
}
}
In this combination output is like this:
0 Thread B
1 Thread B
2 Thread B
3 Thread B
4 Thread B
Main thread says hello!
And after commenting threadB part and uncommenting threadA, there is something like this:
0 Thread A
1 Thread A
2 Thread A
3 Thread A
4 Thread A
0 main
1 main
2 main
3 main
4 main
Main thread says hello!
Can someone tell me, what exactly causes such difference? Any hints appreciated. I suppose that, it is connected with overriding java.lang.Thread.run() method in threadA, but why threadB, does not run runnable in second case?
Upvotes: 2
Views: 1685
Reputation: 213351
Second Case (threadA.run()
) : -
Since threadA
is a reference of type UsingThreadExtension
: -
UsingThreadExtension threadA = new UsingThreadExtension("Thread A");
So calling the run
method on threadA like this: -
threadA.run();
will execute the run method of UsingThreadExtension
in the main thread only. And thus, the name of the thread is main in 0 main, 1 main, etc.
in the 2nd output.
First Case (threadB.run()
) : -
Since threadB
is a reference of type Thread
pointing to an instance of Thread
only.
Thread threadB = new Thread(runnableImplementation, "Thread B");
So, invoking the run method on it like: -
threadB.run();
will execute the run() method overriden in the Thread class again in the main
thread only. But since run() method of Thread class doesn't actually print anything. And hence you didn't get any output for threadB.run()
.
Upvotes: 4
Reputation: 122414
When you construct a Thread
passing it a Runnable
instance, it stores that instance away in a private field. The default run()
method of java.lang.Thread
is essentially
if(target != null) target.run();
So presumably what happens in your thread B case is that you start()
the thread, and when it completes it internally does target = null
. Then when you call the thread's run()
method later it no longer has a reference to the target Runnable
so does not run it.
If you did it the other way round, first calling run()
on the main thread and later calling start()
you'd see both lots of logging.
In the extends Thread
case the run()
method is overridden directly, so this null check is bypassed.
Upvotes: 0
Reputation: 43401
Runnable.run()
doesn't start a new thread, it just runs the method -- just like any other method. If you want to spin off a new thread, you always have to use Thread.start()
(or submit the Runnable
to an executor).
Upvotes: 3