java.lang.IllegalThreadStateException

17

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

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

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

    
задан Jose Hdez 06.09.2011 в 08:51
источник

4 ответа

25

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

    
ответ дан Peter Lawrey 06.09.2011 в 08:58
источник
16

Нить будет генерировать исключение при вызове 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 , если это поможет.

ОБНОВЛЕНИЕ. В ответ на ваши комментарии, если вы прервите поток, который в вашем случае, я предполагаю, установит флаг running в значение false, поток будет по-прежнему RUNNABLE . Чтобы возобновить работу над потоком (опять же, я предполагаю, что это то, что вы хотите сделать), вы снова измените флаг running . Вызов start завершится неудачно, потому что он уже запущен. Вы также можете позволить потоку умереть на перерыве, а затем просто создать новый экземпляр Thread и «запустить», который будет использоваться в качестве альтернативы.

    
ответ дан Toby 06.09.2011 в 11:47
источник
0

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

  • Из основного метода: 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.

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

    
ответ дан Jose Hdez 06.09.2011 в 11:25
источник
0

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

public void start()

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

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

  

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

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

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

ответ дан Ravindra babu 23.10.2017 в 18:48
источник