Pacerier
Pacerier

Reputation: 89663

Why does a java.lang.Thread not call the run() method of its explicit java.lang.Runnable when started?

The Java docs state that if we supplied a Runnable target when creating a new thread, .start() of that thread would run the run() method of the supplied runnable.

If that's the case, shouldn't this test code prints "a" (instead of printing "b") ?

public class test {
    public static void main(String[] args) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                System.out.println("a");
            }
        };
        Thread t = new Thread(r) {
            @Override
            public void run() {
                System.out.println("b");
            }
        };
        t.start();
    }
}

Upvotes: 6

Views: 7336

Answers (8)

Bhesh Gurung
Bhesh Gurung

Reputation: 51030

You are actually extending the Thread class and calling start on the instance of that anonymous subclass.

I think the confusion is that the "Java Doc" is for the java.lang.Thread class not for your class that extends that class.

e.g.

Runnable r = new Runnable() {
    @Override
    public void run() {
        System.out.println("a");
    }
};
Thread t = new Thread(r);

Now, if it does not call that run then java doc is wrong. Which is not true.

Upvotes: 1

Matt K
Matt K

Reputation: 6708

You are calling start() method. Reading the docs in the link you provided it states:

public void start() Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.

You should call the run() method if you would like to call the Runnable object's run method.

public void run() If this thread was constructed using a separate Runnable run object, then that Runnable object's run method is called; otherwise, this method does nothing and returns.

Upvotes: 1

Zéychin
Zéychin

Reputation: 4205

The documentation that I have says this: "Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread." which means that it should print b instead of a, since you have overridden the run() method of Thread.

Upvotes: 1

user949300
user949300

Reputation: 15729

The default implementation of Thread.run() does what the javadocs say (look at the source code)

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

However, Thread.run() is public, and you overrode it, so it calls your println("b"), and totally ignores the Runnable passed in the constructor. Arguably, Thread.run() should be final, but it isn't.

Upvotes: 3

Paul
Paul

Reputation: 20061

The first block overrides run in Runnable. The second block overrides run in Thread. When you call start on a Thread, its run method is invoked. The default run method in Thread calls the Runnable.run method but since you overrode Thread.run there is no code to start the Runnable - only your code to print 'b'.

Upvotes: 1

chrisbunney
chrisbunney

Reputation: 5946

You have overridden the default implementation of Thread.run() in what I guess is an anonymous subclass, hence what the JavaDoc says no longer applies.

If you try

public class Test {
public static void main(String[] args) {

    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("a");
        }
    }) .start();
}
}

You get the answer you expect, a.

Upvotes: 1

Peter Lawrey
Peter Lawrey

Reputation: 533560

The default implementation is to call the Runnable. However you are overriding the default implementation and NOT calling the runnable. The simplest way to fix this is

    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("a");
        }
    }) {
        @Override
        public void run() {
            super.run(); // call the default implementation.
            System.out.println("b");
        }
    }.start();

Upvotes: 9

user802421
user802421

Reputation: 7505

Because you are overriding Thread.run() method.

Here is the implementation of Thread.run():

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

try:

}) {
    @Override
    public void run() {
        super.run(); // ADD THIS LINE
        System.out.println("b");
    }
}.start();

You will get ab.

Upvotes: 16

Related Questions