Почему бы не начать нить в конструкторе? Как прекратить?

Я изучаю, как использовать потоки в Java. И я написал класс, который реализует Runnable для одновременного запуска другого потока. Основной поток обрабатывает прослушивание последовательного порта, где, когда второй поток обрабатывает отправку данных на тот же порт.

public class MyNewThread implements Runnable {
    Thread t;

    MyNewThread() {
        t = new Thread (this, "Data Thread");
        t.start();
    }

    public void run()  {
        // New Thread code here 
    }

В первом потоке начинается второе:

public class Main {
    public static void main(String[] args) throws Exception{
        new MyNewThread();
        // First thread code there
    }  
}

Это работает, но мой компилятор отмечает предупреждение: опасно запускать новый поток в конструкторе. Почему это?

Вторая часть этого вопроса: как, если у меня есть цикл, запущенный в одном потоке (поток прослушивания последовательного порта), и я набираю команду exit во втором потоке. Как я могу завершить первый поток? Спасибо.

Ответ 1

К вашему первому вопросу: Запуск потока в конструкторе, проходящем в this escapes this. Это означает, что вы фактически выдаете ссылку на свой объект, прежде чем он будет полностью построен. Поток начнется до завершения вашего конструктора. Это может привести к любым видам странного поведения.

К вашему второму вопросу: нет приемлемого способа заставить другой поток останавливаться в Java, поэтому вы должны использовать переменную, которую поток проверял бы, стоит ли останавливаться или нет. Другой поток установил бы его, чтобы указать, что первый поток остановится. Переменная должна быть нестабильной или все обращения синхронизированы для обеспечения правильной публикации. Вот какой-то код, который будет похож на то, что вы хотите.

public class MyNewThread implements Runnable {

    private final Thread t;
    private volatile boolean shouldStop = false;

    MyNewThread() {
        t = new Thread (this, "Data Thread");
    }

    public void start() {
        t.start();
    }

    public void stop() {   
         shouldStop = true;
    }

    public void run()  {
         while(!shouldStop)
         {
             // do stuff
         }
    }
}

Независимо от того, что хочет создать и запустить поток, выполните:

MyNewThread thread = new MyNewThread();
thread.start();

Независимо от того, что хочет остановить поток, выполните:

thread.stop();

Ответ 2

Давайте рассмотрим базовый пример:

class MyClass implements Runnable{
   int a = 0;
   String b = null;

   public MyClass(){
       new Thread(this).start();
       b = "Foo";
   }

   public void run(){
      a = b.length(); //can throw NullPointerException
   }
}

В этом случае MyClass.this, как говорят, избегает конструктора. Это означает, что объект доступен для ссылки, но все его поля, которые строятся в конструкторе, могут не создаваться. Чтобы сделать это на другом уровне, что если b был final Вы ожидали бы, что он будет доступен, но он не будет обеспечен. Это известно как частично построенные объекты и совершенно легально в java.

Ответ 3

о втором вопросе, вы можете проверить, был ли второй поток завершен или нет с помощью метода isAlive, и если да, используйте ключевое слово break, чтобы отключить цикл для первого потока, то будет прекращено, если ничего не нужно делать

public class MyNewThread implements Runnable {
Thread t;

MyNewThread() {
    t = new Thread (this, "Data Thread");
    t.start();
}

public void run()  {

   reading code ................
    // New Thread code here 
}

public class Main {
public static void main(String[] args) throws Exception{
   MyNewThread thread = new MyNewThread();

while(true)
{
    listening code ...................

    if(!thread.t.isAlive())
      break;
 }

}  
}

Ответ 4

Вторая часть этого вопроса: как, если у меня есть цикл, запущенный в одном поток (поток прослушивания последовательного порта) и я набираю команду exit в моем вторая нить. Как я могу получить первый поток заканчивается?

Продолжайте цикл, пока не будет достигнуто условие. Например:

public void run() {
    while ( !inputConsole.getCommand().equals("exit") ) {
        //Do Something
        Thread.sleep(1000); //put thread to sleep for 1 second
    }
}