【问题标题】:Future.get() gets interrupted always with an InterruptedExceptionFuture.get() 总是被 InterruptedException 中断
【发布时间】:2011-05-15 04:25:39
【问题描述】:

我对 Java 中的 Future.get() 有一个奇怪的问题。它总是返回一个InterruptedException,但奇怪的是异常的原因是null,所以我不知道是谁打断了我..

情况变得更糟,因为我在调用 get() 之前进行了检查,而 Future 要做的工作已经完成。

这是负责下面输出的代码。 f 是 Future,并且可调用返回一个 HashMap,其中 Agent 并不真正相关。抱歉,如果打印行太多,我只是想提供尽可能多的信息。 callable 的 call 方法现在是一个简单的 System.out.println("Hola soy agente"),正如您将看到的那样,它会被打印出来,这意味着 callable 也不会导致异常

代码如下:

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

【问题讨论】:

    标签: java null get future interrupted-exception


    【解决方案1】:

    你在调用get()之前检查过线程的中断标志了吗?您可以使用Thread.currentThread().isInterrupted() 来执行此操作。

    有关更多信息,请查看 Future.get() 的 javadoc,了解它为什么会抛出 InterruptedException。

    【讨论】:

    • 太棒了!在get()之前就被打断了!我认为中断的异常来自提交的可调用对象,它位于不同的线程上......如果你能解释一下,我将不胜感激,无论如何做到了。非常感谢。
    • 你可以通过查看 Future 的 javadoc 来了解原因,这里:download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/… get throws an InterruptedException "if the current thread was interrupted while waiting"
    • 令人难以置信的是,我在发帖之前多次访问该页面,但不知何故,我的大脑没有连接到等待线程是这个!很有趣,因为其他人也有同样的误解,这次我在仔细阅读文档后向他们解释了同样的事情。第一次在 stackoverflow 发帖是一次非常有趣的体验!
    【解决方案2】:

    .get() 抛出的裸InterruptedException 表示当前执行线程(调用.get() 的线程)在调用get() 之前被中断,或者在.get() 中被阻塞。这与执行程序线程或其任务之一被中断是一回事。有人或某事正在中断你的“主”线程——或者至少是调用.get()的线程。

    中断不会随机发生——某些代码必须故意造成中断。 只能通过调用 Thread.interrupt() 来启动中断,但是有一些标准的 Java 实用程序会在后台调用它,例如 Future.cancel(true)ExecutorService.shutdownNow()

    AFAIK,没有办法从外部跟踪中断原因的“原因链”或“堆栈跟踪”。您必须查看源代码以确定可以在何处启动中断,从而推断在您的情况下是什么方法调用导致了中断。

    【讨论】:

    • 我完全理解它们不会发生,如果它以这种方式出现,我很抱歉......我想知道它发生在哪里。混乱真的来了,因为我认为有人在打断可调用对象,这是错误的。主线程被中断是完全可以预料到的,因为它属于模拟器……至少现在我知道那个裸露的 InterruptedException 意味着什么。
    • @dgrandes:很公平,我想你完全明白现在发生了什么。祝你好运,多线程可能是一件棘手的事情! :-)
    【解决方案3】:

    Exception 的原因是 Throwable(方法调用不是异常)

    线程只有在你引起它的时候才会被中断,它不会随机发生。

    如果你真的不知道中断来自哪里并想忽略它,你可以先清除它。拨打Thread.interrupted()

    【讨论】:

    • 我知道它是一个 throwable,我是说 callable 没有在任何地方抛出异常。对不起,我表达得如此糟糕。无论如何,调用 interrupted() 允许从 get 获取结果!非常感谢。
    【解决方案4】:

    这表示执行提交的 Callable 的线程被中断。这可能是合法的中断(例如,如果 Callable 执行一些阻塞操作,例如 Thread.sleep 并通过 Thread.interrupt() 显式中断),或者可能是 ExecutorService(假设您正在使用它)正在通过调用 shutDownNow() 关闭。

    您能否将用于创建线程池的代码与您的Callable 实现一起发布?

    【讨论】:

    • 其实我也是这么想的,这个中断应该属于提交的Callable,但事实并非如此。 callable 中的 call 方法的代码实际上是一个 println。 executorservice 非常简单......
    • 不小心按了输入,对不起,服务很简单 private ExecutorService pool = Executors.newCachedThreadPool();如前所述,问题在于提交可调用对象的 currentThread 被中断。仔细阅读文档后,它指出“InterruptedException - 如果当前线程在等待时被中断”。这对发生的事情是有道理的,因为当前线程在启动之前处于中断状态,并且该线程是等待答案的线程,而不是 subitted 可调用线程......我认为。
    猜你喜欢
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    • 2014-07-07
    • 2023-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多