@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, "Дочерний поток # ");
  • Вопрос задан
  • 202 просмотра
Решения вопроса 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.
Ответ написан
Ваш ответ на вопрос

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

Похожие вопросы