Почему бы не запустить поток в конструкторе?Как прекратить? - PullRequest
46 голосов
/ 11 апреля 2011

Я учусь использовать потоки в 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
    }  
}

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

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

Ответы [ 4 ]

45 голосов
/ 11 апреля 2011

К первому вопросу: запуск потока в конструкторе с передачей this экранирует 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();
8 голосов
/ 11 апреля 2011

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

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 называется escape конструктора.Это означает, что объект доступен для ссылки, но все его поля, которые строятся в конструкторе, могут не быть созданы.Чтобы перевести это на другой уровень, что если b было final, вы ожидаете, что оно будет доступно, но это не гарантировано.Это известно как частично построенные объекты и совершенно законно в Java.

0 голосов
/ 10 февраля 2013

по второму вопросу, вы можете проверить, была ли вторая нить прервана или нет, методом 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;
 }

}  
}
0 голосов
/ 11 апреля 2011

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

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

public void run() {
    while ( !inputConsole.getCommand().equals("exit") ) {
        //Do Something
        Thread.sleep(1000); //put thread to sleep for 1 second
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...