Почему java.lang.Thread не вызывает метод run () его явного java.lang.Runnable при запуске? - PullRequest
6 голосов
/ 23 декабря 2011

Документы Java утверждают, что если мы указали Runnable target при создании нового потока, .start() этого потока будет запускать метод run() предоставленного runnable.

Если это так, не должен ли этот тестовый код печатать «a» (вместо «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();
    }
}

Ответы [ 8 ]

16 голосов
/ 23 декабря 2011

Поскольку вы переопределяете метод Thread.run () .

Вот реализация Thread.run () :

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

попробовать:

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

Вы получите ab.

9 голосов
/ 23 декабря 2011

Реализация по умолчанию - вызывать Runnable.Однако вы переопределяете реализацию по умолчанию и НЕ вызываете runnable.Самый простой способ исправить это

    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();
3 голосов
/ 23 декабря 2011

Реализация Thread.run () по умолчанию делает то, что говорят javadocs (посмотрите на исходный код)

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

Однако Thread.run () является общедоступным, и вы переопределите его, так чтовызывает ваш println ("b") и полностью игнорирует Runnable, переданный в конструкторе.Возможно, Thread.run () должен быть окончательным, но это не так.

1 голос
/ 23 декабря 2011

Вы вызываете метод start (). Читая документы по предоставленной вами ссылке, она гласит:

public void start () Заставляет этот поток начать выполнение; Ява Виртуальная машина вызывает метод run этого потока.

Вам следует вызывать метод run (), если вы хотите вызвать метод run объекта Runnable.

public void run () Если этот поток был создан с использованием отдельного Runnable run object, затем вызывается метод run этого Runnable объекта; в противном случае этот метод ничего не делает и возвращает.

1 голос
/ 23 декабря 2011

В документации I говорится следующее: «Заставляет этот поток начать выполнение; виртуальная машина Java вызывает метод run этого потока. » это означает, что он должен напечатать b вместо a, поскольку вы переопределили метод run() для Thread.

1 голос
/ 23 декабря 2011

Первый блок переопределяет run в Runnable. Второй блок переопределяет run в Thread. Когда вы вызываете start для Thread, вызывается его метод run. Метод run по умолчанию в Thread вызывает метод Runnable.run, но поскольку вы переопределили Thread.run, кода для запуска Runnable нет - только ваш код для печати 'b'.

1 голос
/ 23 декабря 2011

Вы переопределили реализацию по умолчанию Thread.run() в том, что, как мне кажется, является анонимным подклассом, следовательно, то, что говорит JavaDoc, больше не применяется.

Если вы попробуете

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

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

Вы получите ожидаемый ответ, a.

1 голос
/ 23 декабря 2011

Вы фактически расширяете класс Thread и вызываете start в экземпляре этого анонимного подкласса.

Я думаю, что путаница в том, что "Java Doc" предназначен для класса java.lang.Thread, а не для вашего класса, расширяющего этот класс.

, например

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

Теперь, если он не называет это run, тогда Java-документ неверен. Что не соответствует действительности.

...