@n199a
Java

Почему не запускается дочерний поток?

Имеется два класса:
- Main (в котором запускается главный поток);
Исходник

public class Main {

    public static void main(String[] args) {
        Runnable r = new PrintMessage();

        try {
            for(int i = 0; i < 5; i++){
                Thread.sleep(1000);
                System.out.println("Главный поток # " + i);

            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("END");
    }
}


- PrintMessage (в котором планируется запуск дочернего потока).
Исходник

public class PrintMessage implements Runnable {
    private Thread thread;

    public PrintMessage(){
        thread = new Thread("Дочерний поток # ");
        thread.start();
    }

    @Override
    public void run() {
        try {
            for(int i = 0; i < 7; i++){
                Thread.sleep(1000);
                System.out.println(thread.getName() + i);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}



Вопрос:
В классе PrintMessage создается поток с помощью реализации интерфейса Runnable и создается объект класса Thread.
Почему, если в конструкторе Thread не указать target – экземпляр класса реализующего интерфейс Runnable вот так (как ниже), то дочерний поток не запускается?
thread = new Thread(this, "Дочерний поток # ");
  • Вопрос задан
  • 192 просмотра
Решения вопроса 1
xez
@xez Куратор тега Java
TL Junior Roo
Контракт такой:
/**
     * Allocates a new {@code Thread} object. This constructor has the same
     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
     * {@code (null, null, name)}.
     *
     * @param   name
     *          the name of the new thread
     */
    public Thread(String name) {
        init(null, null, name, 0);
    }


Т.е., если не передавать в конструктор target, это то же самое, что и вызвать конструктор: Thread(null, "Дочерний поток # ");

При этом
@param target the object whose run() method gets called


Метод run:
/**
     * If this thread was constructed using a separate
     * <code>Runnable</code> run object, then that
     * <code>Runnable</code> object's <code>run</code> method is called;
     * otherwise, this method does nothing and returns.
     * <p>
     * Subclasses of <code>Thread</code> should override this method.
     *
     * @see     #start()
     * @see     #stop()
     * @see     #Thread(ThreadGroup, Runnable, String)
     */
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }


Т.е. вы передаете в конструктор null, и в методе run потом ничего не происходит
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
mayton2019
@mayton2019 Куратор тега Java
Bigdata Engineer
Здесь заложена потенциальная ошибка гонок. Главный и дочерний потоки не синхронизируются через объекты синхронизации. Это означает что если дочерний объект тупанул в фазе например JIT компилляции то главный его не будет ждать и завершит приложение. И мы можем (теоретически) не увидеть даже следов работы дочернего потока. Искусственные паузы sleep() не являются механизмом синхронизации и их не стоит использовать для той цели которую хочет достичь автор. Нужен нормальный join. Или ожидание финала ThreadPool.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
Bell Integrator Ульяновск
До 400 000 ₽
Bell Integrator Хабаровск
До 400 000 ₽
Bell Integrator Ижевск
До 400 000 ₽
19 апр. 2024, в 13:31
10000 руб./за проект
19 апр. 2024, в 13:12
35000 руб./за проект
19 апр. 2024, в 13:06
6000 руб./за проект