Future.get() gets interrupted always with an InterruptedException
Asked Answered
B

4

9

I have a WEIRD problem with Future.get() in Java. It returns always with an InterruptedException, however the weird thing is that the cause of the Exception is null, so I cant tell who interrupted me..

It gets even worse because I check before calling get(), and the job Future has to do is already done.

Here is the code responsible for the output below. f is the Future, and the callable returns a HashMap where Agent is not really relevant. Sorry if there are too many printlines, I'm just trying to give as mush info as I can. The call method from callable is for now a simple System.out.println("Hola soy agente") that as you will see, gets printed, meaning that the callable didn't cause the exception either

Here is the code:

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();
    }

And the output

 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)

In case you want to see where I sumbit the callable to the threadpool... then this would be the code for it

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

and afterwards I iterate over this Set with

    for(Future<HashMap<Integer, Agent>> f : agentFutureSet)
    try
    {
              //Here goes the code at the beginning
Bolt answered 24/11, 2010 at 15:27 Comment(0)
B
13

Did you check the thread's interrupt flag before calling get()? You can do this with Thread.currentThread().isInterrupted().

For more info look at the javadoc for Future.get() to see why it would throw an InterruptedException.

Boltzmann answered 24/11, 2010 at 15:37 Comment(3)
That was brilliant! It was interrupted before get()! I thought the interrupted exception came from the submitted callable, which was on a different thread... if you can explain, I would appreciate it, anyways that did it. Thanks a lot.Bolt
You can see why by looking at the javadoc for Future, here: download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/… get throws an InterruptedException "if the current thread was interrupted while waiting"Boltzmann
Incredibly enough, I went to that page many times before posting here, and somehow my brain just didnt connect that the waiting thread was this one! Funny because somebody else had the same misconception and I explained to them this very same thing after reading the documentation CAREFULLY this time. It has been a very fun first posting experience at stackoverflow!Bolt
M
8

A bare InterruptedException being thrown from .get() indicates that the current thread of execution (the thread calling .get()) was interrupted before calling get(), or while blocked in .get(). This is not the same thing as an executor thread or one of its tasks being interrupted. Someone or something is interrupting your "main" thread -- or at least the thread calling .get().

Interruptions do not happen randomly -- some code has to intentionally cause the interruption. An interrupt can only be initiated by a call to Thread.interrupt(), but there are a few standard Java utilities that call this behind the scenes, like Future.cancel(true) and ExecutorService.shutdownNow().

AFAIK, there is no way of externally tracking the "cause chain" or "stack trace" of the cause of interruption. You must look to the source code to determine where interruptions can be initiated, and thus deduce what method call(s) are causing the interruption in your case.

Murielmurielle answered 24/11, 2010 at 16:20 Comment(2)
I completely understand that they dont just happen, Im sorry if it came out that way... what I wanted to know is where it was happening. The confusion really came because I thought somebody was interupting the callable, which is wrong. The main thread getting interrupted was something completely expected since it belongs to a simulator...at least now I know what that bare InterruptedException means.Bolt
@dgrandes: fair enough, I think you understand fully what's going on now. Best of luck to you, multithreading can be tricky business! :-)Murielmurielle
B
2

The cause of an Exception is a Throwable (a method call is not an exception)

The thread will only be intrrupted if you cause it to be, it won't happen randomly.

If you really have no idea where the interrupt is coming from and want to ignore it you can clear it first. call Thread.interrupted()

Brisbane answered 24/11, 2010 at 15:37 Comment(1)
I know its a throwable, I was saying that the callable did not throw an exception anywhere. Sorry for expressing myself so badly. Anyways you are, calling interrupted() allowed to get the result from get! Thanks a lot.Bolt
C
0

This is indicative of the thread executing the submitted Callable becoming interrupted. This could be a legimate interruption (for example if the Callable performs some blocking operation such as Thread.sleep and is interrupted explicitly via Thread.interrupt()), or it could be that the ExecutorService (assuming you're using this) is being shut down via a call to shutDownNow().

Can you please post the code used to create your thread pool along with your Callable implementation?

Cyanide answered 24/11, 2010 at 15:40 Comment(2)
Actually that is exactly what I thoght, that this interruption would belong to the submitted Callable, yet that is not the case. The code for the call method in the callable is literally a println. The executorservice is pretty straight forward...Bolt
Pressed enter accidentally, sorry, the serivce is pretty straight forward private ExecutorService pool = Executors.newCachedThreadPool(); As answered before, the problem was that the currentThread, submitting the callables, was interrupted. Upon reading the documentation carefully, it states "InterruptedException - if the current thread was interrupted while waiting". Which makes sense with what happened, because the current thread was in an interrupted state before starting and that thread is the one that is waiting for the answer, and not the subitted callable thread...I think.Bolt

© 2022 - 2024 — McMap. All rights reserved.