Подтвердить что ты не робот

Java.lang.IllegalThreadStateException

Я работаю с потоками. Однако, когда я пытаюсь запустить поток, я получаю исключение. В конкретном java.lang.IllegalThreadStateException. Мой код:

public void readCommand() {
    readThread = new Thread("Thread for reading") {
        public void run() {
            while (running) {
                readBuffer = usbservice.receiveData();
                put(readBuffer);
            }
        }
    };
    readThread.start();
}

В чем проблема?

4b9b3361

Ответ 1

Вы сохраняете поток в поле. Если метод вызывается в двух потоках, readThread.start() можно вызвать дважды для одного потока. Вы должны убедиться, что readCommand не вызывается несколько раз и, возможно, не запускает readThread еще раз, если он уже запущен. например вы можете синхронизировать метод и проверить readThread перед тем, как начать.

Ответ 2

Поток будет генерировать исключение при вызове start, если состояние потока (полученное с помощью Thread.currentThread().getState() является чем-то иным, чем NEW.

Источник;

public synchronized void start() {
    /*
     * A zero status value corresponds to state "NEW".
     */
    if (threadStatus != 0)
        throw new IllegalThreadStateException();
    group.add(this);
    start0();
    if (stopBeforeStart) {
        stop0(throwableFromStop);
    }
}

Это означает, что ваш поток находится в одном из других состояний, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING или TERMINATED.

Вы можете посмотреть состояние потоков через дамп потока или JConsole, чтобы узнать, что делает ваша. Вы можете программно взять дамп потока прямо перед вызовом start, используя что-то вроде tempus-fugit, если это поможет.

UPDATE: в ответ на ваши комментарии, если вы прервите поток, который в вашем случае, я предполагаю, установит флаг running в значение false, поток будет RUNNABLE. Чтобы возобновить работу над потоком (опять же, я предполагаю, что вы хотите сделать), вы снова измените флаг running. Вызов start завершится неудачно, поскольку он уже запущен. Вы также можете позволить потоку умереть при прерывании, а затем просто создать новый экземпляр Thread и "запустить", который будет использоваться в качестве альтернативы.

Ответ 3

Фактически, процесс вызова:

  • Из основного метода: controller.main(usbservice);

  • В объекте контроллера:

    @Override
    public void main(Object argv) {
        if(this.writer == null)
            this.writer = new CommandWriting(usbservice);
        if(this.reader == null)
            this.reader = new CommandReading(usbservice);
        reader.readCommand();
    }
    
  • В объектном читателе используется метод readCommand.

Затем он вызывается только один раз.

Ответ 4

Посмотрите страницу документации о оракуле о Thread.start()

public void start()

Заставляет этот поток начинать выполнение; виртуальная машина Java вызывает метод запуска этого потока.

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

Невозможно запустить поток более одного раза. В частности, нить не может быть перезапущена после завершения выполнения.

Броски: IllegalThreadStateException - если поток уже запущен.

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