Прерывать поток, который ожидает блокирующего действия? - PullRequest
5 голосов
/ 30 ноября 2009

Я запускаю поток, основное действие которого состоит в том, чтобы вызвать прокси-сервер с помощью функции блокировки и ждать, пока он что-то даст.

Я использовал известный шаблон энергозависимого логического значения и прерывания, но я не уверен, что он будет работать: когда я пытался добавить блок перехвата для InterruptedException, я получаю ошибку:

Недоступный блок перехвата для InterruptedException. Это исключение никогда не выдается из тела оператора try

Так что, если я никогда не получу InterruptedException, это означает, что я никогда не выйду из действия блокировки - таким образом, никогда не остановлюсь.

Я немного озадачен. Есть идеи?

  public void run() {    
    Proxy proxy = ProxyFactory.generateProxy();
    Source source;

    while (!isStopped) {
      try {
        source = proxy.getPendingSources();
        scheduleSource(source);
      } catch (Exception e) {
        log.error("UnExpected Exception caught while running",e);
      }
    }
  }

  public void stop() {
    this.isStopped = true;
    Thread.currentThread().interrupt();
  }

Ответы [ 5 ]

12 голосов
/ 30 ноября 2009

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

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

Наконец, что такое метод блокировки? Это scheduleSource()? Если этот метод не выдает InterruptedException, вы не сможете его перехватить.

Попробуйте следующее:

private final AtomicReference<Thread> currentThread = new AtomicReference<Thread>();

public void run() {
    Proxy proxy = ProxyFactory.generateProxy();
    Source source;

    currentThread.set(Thread.currentThread());

    while (!Thread.currentThread().isInterrupted()) {
        try {
            source = proxy.getPendingSources();
            scheduleSource(source);
        } catch (Exception e) {
            log.error("UnExpected Exception caught while running", e);
        }
    }
}

public void stop() {
    currentThread.get().interrupt();
}
11 голосов
/ 30 ноября 2009

Только несколько четко определенных «методов блокировки» являются прерываемыми. Если поток прерывается, устанавливается флаг, но больше ничего не произойдет, пока поток не достигнет одной из этих четко определенных точек прерывания.

Например, вызовы read() и write() прерываются, если они вызываются в потоках, созданных с помощью InterruptibleChannel. Если в качестве начальной точки используется Socket, то вызов interrupt() для Thread, заблокированного в чтении, не имеет никакого эффекта. Обратите внимание, что если блокирующая операция ввода-вывода успешно прерывается, основной канал закрывается.

Другой большой класс прерываемых операций - это те, которые генерируются различными блокирующими операциями над классами в пакетах java.util.concurrent. Конечно, оригинальный wait() метод также является прерываемым.

Методы блокировки могут быть определены путем поиска throws InterruptedException в сигнатурах их методов. Они также должны быть хорошо документированы, чтобы описать любые побочные эффекты прерывания.

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

2 голосов
/ 30 ноября 2009

хорошо, люди, не убивайте меня за это.

Я экспериментировал с Thread.stop () для удовольствия, чтобы выкинуть поток из блокирующего действия, поймать ThreadDeath, сохранить целевой поток живым и двигаться дальше.

Кажется, работает. Мир не заканчивается. Но я просто говорю. Вы несете ответственность за свои собственные действия. Почему я рэп?

2 голосов
/ 30 ноября 2009

Вы stop вызываете метод interrupt не в том потоке. Thread.currentThread() - это прерывание, которое не прерывается.

1 голос
/ 30 ноября 2009

Как вы вызываете стоп из исполняющего потока?
Если вы вызовете stop () из другого потока, вы убьете его, а не поток, запущенный в блоке try / catch.

...