Вызов interrupt () в потоке, но он никогда не прерывается - PullRequest
3 голосов
/ 22 января 2012

Я написал класс VideoProcessor, который выполняет тяжелую обработку видео.Если «запущено», создается новый поток, и ссылка сохраняется в поле videoProcessingThread .Теперь проблема заключается в следующем:

videoProcessingThread.interrupt();

Это, похоже, не имеет никакого эффекта, поскольку isInterrupted () никогда не оценивается как true.Я также добавил другие проверки прерываний, просто чтобы быть уверенным;но они тоже не "работают".Я реализовал обходной путь:

videoProcessingThread.kill();

Кажется, что это на самом деле «убивает» поток.Метод kill устанавливает для булевой переменной kill значение true, и оно вычисляется правильно, и поток возвращает.

videoProcessingThread = new Thread() {
    boolean kill = false; // workaround 

    public void run() {
        // init stuff
        while (currentFrameIndex < totalFrames) {
            if (isInterrupted()) { 
                System.out.println("isInterrupted");

                return;
            }
            if (Thread.interrupted()) {
                System.out.println("interrupted");

                return;
            }
            if (Thread.currentThread().isInterrupted()) {
                System.out.println("Thread.currentThread().isInterrupted()");

                return;
            }
            if (kill) {
                System.out.println("killed");

                return;
            }
        }
        // heavy processing
    }

    public void kill() {
        kill = true;
    }
}

Что я делаю не так?

Ответы [ 2 ]

1 голос
/ 22 января 2012

Прежде всего, вызов interrupt() не может фактически установить статус прерывания, пожалуйста, смотрите здесь, в javadocs точные условия, иногда он просто выдаст InterruptedException.

Во-вторых, фактический вызов метода interrupted() также очистит статус прерывания в дополнение к его возвращению, поэтому следующий вызов isInterrupted() (который только возвращает текущее состояние, но не очищает это) может не делать то, что вы ожидаете.

Использование логической переменной, вероятно, не является плохим методом для достижения этой цели. Вы можете прочитать эту статью , в которой подробно рассказывается, что именно происходит, когда вы пытаетесь прервать поток, и как сделать это более или менее надежно.

1 голос
/ 22 января 2012

Ваш kill не гарантированно будет работать, если только он не изменчив.

Поток прерывается только при вызове операции, которая проверяет этот флаг. Некоторые операции NIO выдают исключение, если вы вызываете interrupt()

В большинстве случаев использование interrupt() аналогично установке флага энергозависимости. т. е. ваша задача должна регулярно ее проверять. Единственный безопасный способ уничтожить поток - запустить его в своем собственном процессе.

Если у вас есть поток, который является актером (он только изменяет локальную память потока), вы можете рассмотреть использование stop (). Основная проблема в том, что вы можете оставить в памяти измененный поток в несогласованном состоянии. Если вы изолируете память для этого потока и удалите ее, если поток остановлен, это должно работать нормально.

...