tomi891
tomi891

Reputation: 85

Java 6 Threads - different behaviour with "implements Runnable" and "extends Thread"

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

Answers (3)

Rohit Jain
Rohit Jain

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

Ian Roberts
Ian Roberts

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

yshavit
yshavit

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

Related Questions