Рабочие потоки ScheduledExecutorService сохраняют прерванный статус после FutureTask.cancel(true)

У меня есть задача, которую я планирую периодически запускать через ScheduledThreadPoolExecutor.scheduleAtFixedRate(task, rate, ...). Пользователь может отменить эту задачу вручную, что вызывает ScheduledFuture.cancel(true). По какой-то причине, возможно, в зависимости от того, когда они отменяют эту задачу, рабочий поток (который исполнитель использовал для запуска моей задачи) остается в прерванном состоянии после выхода из метода run() моей задачи.

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

У меня есть два вопроса:

  • Как получается, что рабочий поток остается в состоянии, когда установлен статус прерывания?
  • Почему реализация по умолчанию не очищает статус прерывания перед запуском новой задачи?

person Justin    schedule 10.11.2010    source источник
comment
Я не мог видеть это поведение, несмотря на использование различных таймингов. Можете ли вы описать, как воспроизвести это надежно?   -  person erickson    schedule 11.11.2010
comment
Хотел бы я сам понять это лучше, сама задача использует ArrayBlockingQueue.take(), который использует ReentrantLock.lockInterruptably(). Я считаю, что это как-то связано с этим, я все еще пытаюсь понять, как это происходит (вторая часть вопроса)   -  person Justin    schedule 11.11.2010
comment
Какой JDK (версия, производитель, ОС и т. д.) вы используете?   -  person sjlee    schedule 11.11.2010
comment
Я думаю, что нашел это: задача запускает отдельный поток предварительной выборки, который помещает рабочие единицы в очередь, условие гонки завершения работы оставляет рабочую единицу терминатора в очереди, вызывая досрочное завершение работы, которое повторно запускает состояние гонки (и прерывание потока) .   -  person Justin    schedule 11.11.2010


Ответы (2)


* How is it that the worker thread is left in a state where the interrupt status is set?
* Why does the default implementation not clear the interrupt status before starting a new task?

Ответы:

  • Он не остается в прерванном состоянии.
  • Реализация работает, но вы смотрите не в том месте

Из кода библиотеки Oracle:

        /*
         * Ensure that unless pool is stopping, this thread
         * does not have its interrupt set. This requires a
         * double-check of state in case the interrupt was
         * cleared concurrently with a shutdownNow -- if so,
         * the interrupt is re-enabled.
         */
        if (runState < STOP &&
            Thread.interrupted() &&
            runState >= STOP)
            thread.interrupt();

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

person Tim Bender    schedule 10.11.2010
comment
Правда что! Я увидел этот фрагмент кода в первый раз и неправильно истолковал его как применимый только при закрытии пула. Я до сих пор понятия не имею, как я получаю прерванное исключение; возможно, я отменяю и планирую задачу одновременно, не осознавая этого. - person Justin; 11.11.2010
comment
Если пользователь отменяет во время выполнения задачи, как вы обрабатываете InterruptedException, которое будет сгенерировано при следующем заблокированном вызове? - person Tim Bender; 11.11.2010
comment
Я просто ловлю его, регистрирую и возвращаю (это перезапускаемый пакетный процесс) - person Justin; 11.11.2010

Как пользователь прерывает поток? Если они используют компонент пользовательского интерфейса, ваша проблема может быть связана с проблемами синхронизации с потоком отправки событий.

person Bill Horvath    schedule 10.11.2010
comment
Это не качающееся приложение. Как говорится в вопросе: задача (FutureTask) отменяется каким-то произвольным потоком через ScheduledFuture.cancel(true). - person Justin; 11.11.2010