Future.get () всегда прерывается с InterruptedException - PullRequest
5 голосов
/ 24 ноября 2010

У меня странная проблема с Future.get () в Java. Он всегда возвращается с InterruptedException, однако странная вещь заключается в том, что причина исключения равна нулю, поэтому я не могу сказать, кто прервал меня ..

Это становится еще хуже, потому что я проверяю перед вызовом get (), и работа, которую Future должна сделать, уже выполнена.

Вот код, отвечающий за вывод ниже. f - это будущее , и вызываемый объект возвращает HashMap, где агент на самом деле не имеет значения. Извините, если есть слишком много печатных строк, я просто пытаюсь дать как можно больше информации. Метод вызова из callable на данный момент является простым System.out.println("Hola soy agente"), который, как вы увидите, будет напечатан, а это означает, что вызываемый не вызвал исключение либо

Вот код:

try
    {
        System.out.println(f.isDone());        //true
        System.out.println(f.isCancelled());   //false
        System.out.println(f.toString());      //FutureTask
        newModdedAgents.putAll(f.get());
    }catch(InterruptedException e)
    {
        System.out.println(f.isDone());        //true
        System.out.println(f.isCancelled());   //false
        System.err.println(e);                 //It is an interruptedException
        System.err.println(e.getCause());     //???? null?
        e.printStackTrace();
    }

А на выходе

 Hola soy agente
 true
 false
 java.util.concurrent.FutureTask@1c4c94e5
 true
 false
 java.lang.InterruptedException
 null

java.lang.InterruptedException
at     java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1302)
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:248)
at java.util.concurrent.FutureTask.get(FutureTask.java:111)
at com.pf.simulator.Simulation.simulateStep(Simulation.java:217)
at com.pf.gui.ButtonPanel.doWork(ButtonPanel.java:141)
at com.pf.gui.ButtonPanel$1$1.construct(ButtonPanel.java:198)
at com.pf.gui.SwingWorker$2.run(SwingWorker.java:117)
at java.lang.Thread.run(Thread.java:636)

Если вы хотите увидеть, где я могу передать вызываемое в пул потоков ... тогда это будет код для него

    for(Callable<HashMap<Integer, Agent>> c : agentCallables)
    {
        Future<HashMap<Integer,Agent>> future = pool.submit(c);
        agentFutureSet.add(future);
    }

и после этого я перебираю этот Набор с

    for(Future<HashMap<Integer, Agent>> f : agentFutureSet)
    try
    {
              //Here goes the code at the beginning

Ответы [ 4 ]

9 голосов
/ 24 ноября 2010

Вы проверяли флаг прерывания потока перед вызовом get()? Вы можете сделать это с Thread.currentThread().isInterrupted().

Для получения дополнительной информации посмотрите на javadoc для Future.get () , чтобы понять, почему он вызовет исключение InterruptedException.

6 голосов
/ 24 ноября 2010

Пустое InterruptedException, выбрасываемое из .get(), указывает, что текущий поток выполнения (поток, вызывающий .get()) был прерван перед вызовом get() или заблокирован в .get(). Это не то же самое, что поток выполнения или прерывание одной из его задач. Кто-то или что-то прерывает ваш «основной» поток - или, по крайней мере, поток, вызывающий .get().

Прерывания не происходят случайно - некоторый код должен преднамеренно вызывать прерывание. Прерывание может только быть инициировано вызовом Thread.interrupt(), но есть несколько стандартных утилит Java, которые вызывают это за кулисами, например Future.cancel(true) и ExecutorService.shutdownNow().

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

1 голос
/ 24 ноября 2010

Причиной исключения является Throwable (вызов метода не является исключением)

Поток будет прерван только в том случае, если вы его вызвали, он не произойдет случайно.

Если вы действительно не знаете, откуда исходит прерывание и хотите его игнорировать, вы можете сначала его очистить.звонок Thread.interrupted()

0 голосов
/ 24 ноября 2010

Это указывает на то, что поток, выполняющий отправленный Callable, становится прерванным.Это может быть допустимое прерывание (например, если Callable выполняет некоторую блокирующую операцию, такую ​​как Thread.sleep и прерывается явно через Thread.interrupt()), или это может быть ExecutorService (если вы используете это)завершается с помощью вызова shutDownNow().

Можете ли вы опубликовать код, используемый для создания пула потоков, вместе с вашей реализацией Callable?

...