Как прервать поток с будущим, хочу выполнить некоторую задачу по прерыванию, выпущенному будущим

Я новичок в будущем и многопоточности в java. У меня простая проблема, которая оказалась сложной: у меня есть несколько потоков (у всех есть открытые сеансы), которые открыты бесконечно. Каждый раз, когда один поток генерирует настраиваемое исключение (исключение тайм-аута в сеансе), я должен прервать все потоки и корректно закрыть все сеансы. Что я делаю, так это то, что я сохраняю будущие объекты, возвращаемые потоками (в ArrayList), перебираю их и выдаю future.cancel для всех, когда один поток генерирует исключение.

private static void futureCancel()
{
        for(int i=0;i<numberStreams;i++)
        {
            Future<String> future=futureList.get(i);
            try{
                future.cancel(true);
                future.get();
            }
            catch(InterruptedException e)
            {
                System.out.println("In interrupted block!");
            } catch (ExecutionException e) {
                e.printStackTrace();
            }       
        }
        return;
    }

Проблема здесь в том, что я не могу добавить InterruptedException в свой код потока из-за некоторых проблем с требованиями и того, как все работает на другой стороне сеансов. Если я выброшу InterruptedException из вызываемого объекта, он не достигнет блока catch, указанного выше. Если я добавляю сон в свой поток (подходит для тестирования) и обрабатываю InterruptedException, он входит в этот блок, как только выдается future.cancel. Что я делаю неправильно?


person Anuja Khemka    schedule 05.02.2014    source источник


Ответы (2)


Futuer#cancel(boolean) javadoc государства

Эта попытка не удастся, если задача уже завершена, уже отменена или не может быть отменена по какой-либо другой причине. В случае успеха, и эта задача не была запущена при вызове отмены, эта задача никогда не должна запускаться. Если задача уже запущена, то параметр mayInterruptIfRunning определяет, следует ли прервать поток, выполняющий эту задачу, при попытке остановить задачу.

Таким образом, либо ExecutorService не выполнил _3 _ / _ 4_ и может удалить его из своей очереди, либо ExecutorService должен вызвать Thread#interrupt(), а ваш _7 _ / _ 8_ код должен обработать его.

Нет другого способа прервать поток через Future интерфейс. Если ваш Runnable не может обрабатывать прерывания, может произойти ряд вещей. Если происходит InterruptedException, оно поднимется до ExecutorService и будет заключено в ExecutionException, которое будет выброшено из Future#get(). Если InterruptedException не происходит в потоке, выполняющем Runnable, ваш Runnable будет продолжать беспрепятственно.

Вам действительно стоит подумать об изменении Runnable для обработки прерываний.

person Sotirios Delimanolis    schedule 05.02.2014
comment
Я понимаю, что мой код Runnable / Callable должен обрабатывать InterruptedException. Я не могу добавить thread.sleep, object.wait или иметь очередь блокировки или что-то еще в коде Runnable / Callable, есть ли способ добавить код для обработки InterruptedException? - person Anuja Khemka; 06.02.2014
comment
Спасибо @SotiriosDelimanolis, это действительно поможет им прояснить мои сомнения относительно будущего. - person Anuja Khemka; 06.02.2014
comment
Чтобы было ясно, call() может бросить InterruptedException. run() не может @AnujaKhemka. - person Gray; 06.02.2014

Если я выброшу InterruptedException из вызываемого объекта, он не достигнет блока catch, указанного выше.

Не будет. Блок InterruptedException catch вокруг future.get() - это когда поток, вызывающий get, прерывается, а не ваш Callable.

Если ваш Callable прерывается и выдает InterruptedException, тогда, когда вы вызываете get(), он вводит ExecutionException, а e.getCause() должно быть InterruptedException.

person Gray    schedule 05.02.2014
comment
Спасибо! Сделал мое понимание намного более ясным относительно будущей отмены. К сожалению, как указано ниже, я предполагаю, что мне придется явно обрабатывать InterruptedException в коде Runnable / Callable. - person Anuja Khemka; 06.02.2014
comment
Без проблем. Вам не нужно обрабатывать InterruptedException в call(), потому что он может бросить @AnujaKhemka. Вы должны обработать это в run(). - person Gray; 06.02.2014