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

В моей программе три потока (не считая основной).

  • поток sleep засыпает 10 секунд;
  • поток checker проверяет, не прерывается ли sleep другим потоком;
  • interrupter прерывает поток sleep, пока он запущен.

А вот и моя программа:

package foobar;

public class Foobar {

    public static void main(String[] args) throws Exception {
        Thread sleep = new Thread(new Sleep());
        sleep.start();

        Thread checker = new Thread(new InterruptedChecker(sleep));
        checker.start();

        Thread interrupter = new Thread(new Interrupter(sleep));
        interrupter.start();
    }
}

class InterruptedChecker implements Runnable {

    private final Thread thread;

    InterruptedChecker(Thread thread) {
        this.thread = thread;
    }

    @Override
    public void run() {
        while (true) {
            if (thread.isInterrupted()) {
                break;
            }
        }
        System.out.println("The thread is interrupted.");
    }
}

class Sleep implements Runnable {

    @Override
    public void run() {
        try {
            Thread.sleep(10 * 1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

class Interrupter implements Runnable {

    private final Thread thread;

    Interrupter(Thread thread) {
        this.thread = thread;
    }

    @Override
    public void run() {
        System.out.println("interrupting...");
        thread.interrupt();
    }
}

Интересно то, что кое-что (довольно много) программа продолжает работать и не выводит сообщение "The thread is interrupted.", что означает, что sleep.isInterrupted() возвращает false, но что-то делает .

Вот java -version моего компьютера (Ubuntu 13.10 64bit):

java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)

После того, как я прочитал Thread.isInterrupted не работает, Thread.interrupted работает выше, я попытался скомпилировать свой код в другом машина, использующая более старый jdk, и она сработала.

И вот java -version машины (Red Hat Enterprise Linux AS, выпуск 4 (Nahant Update 3), 64-разрядная версия):

java version "1.6.0_06"
Java(TM) SE Runtime Environment (build 1.6.0_06-b02)
Java HotSpot(TM) 64-Bit Server VM (build 10.0-b22, mixed mode)

Итак, мой вопрос:

  1. Что-то не так в моей программе?
  2. Если это не так, имеет ли отношение к этой проблеме многоядерный процессор или 64-битная система?

РЕДАКТИРОВАТЬ

Спасибо за комментарий Питера.

Какую проблему ты пытаешься решить?

Я только что прочитал сообщение как я уже говорил в своем комментарии, где в главе «Не глотайте прерывания» говорится, что,

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

Поэтому я не уверен, действует ли поток checker в моей программе как то, что он здесь называется, верхний код . Я просто пытаюсь доказать, что пост правильный. Но, похоже, что-то не так.

0
Wenhao Ji 19 Дек 2013 в 13:19

2 ответа

Лучший ответ

Флаг прерывания сбрасывается, как только он срабатывает. то есть после того, как sleep () был прерван, флаг сбрасывается в false.


РЕДАКТИРОВАТЬ

Поэтому я не уверен, что поток проверки в моей программе действует как то, что здесь называется, как код выше. Я просто пытаюсь доказать, что пост правильный. Но, похоже, что-то не так.

IMHO нет ничего выше другого потока. Обычно вы имеете в виду примерно следующее.

public static void main(String... ignored) throws InterruptedException, ExecutionException {
    ExecutorService es = Executors.newSingleThreadExecutor();
    Future<?> future = es.submit(new Runnable() {
        @Override
        public void run() {
            methodA();
        }
    });
    Thread.sleep(1000);
    future.cancel(true); // interrupts task.
    long start = System.nanoTime();
    try {
        future.get();
    } catch (CancellationException expected) {
        // ignored
    }
    es.shutdown();
    es.awaitTermination(1, TimeUnit.MINUTES);
    long time = System.nanoTime() - start;
    System.out.printf("Time to cancel/shutdown was %.1f milli-seconds%n",
            time / 1e6);
}

private static void methodA() { // doesn't throw any checked exception
    for (int i = 0; i < 100; i++)
        methodB();
}

private static void methodB() {
    boolean conditionWhichIsTrue = true;
    if (conditionWhichIsTrue)
        try {
            Thread.sleep(500);
        } catch (InterruptedException ie) {
            Thread.currentThread().interrupt();
        }
}

Отпечатки

Time to cancel/shutdown was 1.7 milli-seconds

Однако, если вы проглотите прерывание, закомментировав строку Thread.currentThread().interrupt();, остановка займет около 50 секунд, потому что вы прервали только один вызов для перехода в спящий режим.

3
Peter Lawrey 19 Дек 2013 в 10:49

Этот вопрос тоже меня некоторое время беспокоил. После некоторого расследования я получил ответ.

Когда InterruptedChecker проверяет состояние isInterrupted, поток Sleep уже умер. Попробуйте добавить трудоемкий код после Thread.currentThread().interrupt(); в классе Sleep и повторите попытку.

статус "прервано" для потока сбрасывается, когда этот поток завершается.

0
Marko Popovic 26 Апр 2016 в 09:34