【问题标题】:How to interrupt a thread with future, want to perform some task by the interruption issued by future如何用future中断线程,想通过future发出的中断执行一些任务
【发布时间】:2014-02-05 19:24:18
【问题描述】:

我对 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 发出后立即进入该块。我做错了什么?

【问题讨论】:

    标签: java multithreading future cancellation interrupted-exception


    【解决方案1】:

    Futuer#cancel(boolean) javadoc 状态

    如果任务已经完成,则此尝试将失败,已经 已取消,或因其他原因无法取消。如果 成功,并且在调用取消时此任务尚未开始,这 任务永远不应该运行。如果任务已经开始,那么 mayInterruptIfRunning 参数决定线程是否 执行此任务应被中断以试图停止 任务。

    所以ExecutorService 没有执行Runnable/Callable 并且可以将其从其队列中删除,或者它已经执行并且ExecutorService 必须调用Thread#interrupt() 和您的Runnable/@987654330 @代码必须处理它。

    没有其他方法可以通过Future 接口中断线程。如果您的Runnable 没有办法处理中断,那么可能会发生很多事情。如果出现InterruptedException,它将冒泡到ExecutorService 并被包裹在ExecutionException 中,而Future#get() 将抛出该ExecutionException。如果在执行Runnable 的线程中没有出现InterruptedException,您的Runnable 将继续畅通无阻。

    你真的应该考虑改变你的Runnable来处理中断。

    【讨论】:

    • 我知道我的 Runnable/Callable 代码必须处理它“InterruptedException”。我无法在 Runnable/Callable 代码中添加 thread.sleep、object.wait 或阻塞队列或其他内容,有没有办法仍然可以添加代码来处理 InterruptedException?
    • @AnujaKhemka 不,您的代码必须实际支持中断。见官方tutorial
    • 感谢@SotiriosDelimanolis,这真的会帮助他们澄清我对未来的疑虑。
    • 为了清楚起见,call() 可以抛出 InterruptedExceptionrun() 不能@AnujaKhemka。
    【解决方案2】:

    如果我从可调用对象中抛出 InterruptedException,它不会到达上面指定的 catch 块。

    不会的。 InterruptedExceptionfuture.get() 周围的catch 块是调用 get 的线程被中断——而不是你的Callable

    如果您的Callable 被中断并抛出InterruptedException,那么当您调用get() 时,它将进入ExecutionException,而e.getCause() 应该是InterruptedException

    【讨论】:

    • 谢谢!让我对未来取消的理解更加清晰。不幸的是,如下所述,我想我会在 Runnable/Callable 代码中显式处理“InterruptedException”。
    • 没问题。您不必在call() 中处理InterruptedException,因为它可以抛出@AnujaKhemka。你必须在run()处理它。
    猜你喜欢
    • 2014-01-08
    • 2019-10-10
    • 2021-07-31
    • 2021-03-24
    • 1970-01-01
    • 2012-05-05
    • 2021-02-03
    • 2010-11-15
    • 2020-04-26
    相关资源
    最近更新 更多