0

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

4

2 回答 2

2

Futuer#cancel(boolean)javadoc状态

如果任务已完成、已被取消或由于某些其他原因无法取消,则此尝试将失败。如果成功,并且在调用取消时此任务尚未启动,则此任务不应该运行。如果任务已经开始,则 mayInterruptIfRunning 参数确定是否应该中断执行该任务的线程以尝试停止该任务。

因此,要么ExecutorService尚未执行Runnable/Callable并且可以将其从其队列中删除,要么已经执行并且ExecutorService必须调用Thread#interrupt()并且您的Runnable/Callable代码必须处理它。

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

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

于 2014-02-05T19:46:47.073 回答
1

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

它不会。周围的InterruptedExceptioncatch 块future.get()是当调用get 的线程被中断时 - 而不是你的Callable.

如果你Callable被打断并抛出,InterruptedException那么当你调用get()它时,它将进入ExecutionExceptionand the e.getCause()should be InterruptedException

于 2014-02-05T19:40:02.003 回答