【问题标题】:java - How can I get a future's stack trace on TimeoutExceptionjava - 如何在 TimeoutException 上获得未来的堆栈跟踪
【发布时间】:2014-12-18 18:00:58
【问题描述】:

在 java 中,我想确定当 TimeoutException 发生时填充未来结果的线程的当前堆栈。似乎 TimeoutException 提供的堆栈跟踪中的顶部条目仅指示调用 future.get() 的位置,而不是后台线程的状态。例如:

ExecutorService executor = Executors.newSingleThreadExecutor();

Future<String> future = executor.submit(new Callable<String>() {
    @Override
    public String call() throws Exception {
        Thread.sleep(10000);
        return "";
    }
});

try {
    future.get(1, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
    e.printStackTrace();
} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
}

在此示例中,我发现顶部条目是 future.get(1, TimeUnit.MILLISECONDS) 条目,而不是 Thread.sleep(10000)。我希望堆栈跟踪指示 Thread.sleep(10000) 因为这是当前正在执行的。有没有一种优雅的方式来做到这一点?

我发现如果存在实际执行问题,那么 ExecutionException.printStackTrace() 会指出问题发生在后台线程的什么位置。

【问题讨论】:

    标签: java multithreading executorservice


    【解决方案1】:

    如果你有一个引用,t,线程正在运行任务,你可以调用t.getStackTrace();但标准库 ExecutorService 实现不会告诉你哪个线程正在运行任务。

    您可以让任务本身记录运行它的线程:

    class MyTask implements Callable<String> {
        private volatile Thread executorThread;
    
        @Override
        String call() {
            executorThread = Thread.currentThread(); // not getCurrentThread()
            Thread.sleep(10000);
            return "";
        }
    
        Thread getExecutorThread() {
            return executorThread;
        }
    }
    

    这样,当你的主线程超时时,它可以调用myTask.getExecutorThread().getStackTrace();

    ...
    MyTask myTask = new MyTask();
    Future<String> future = executor.submit(myTask);
    ...
    } catch (InterruptedException | ExecutionException e) {
        StackTraceElement[] stack = myTask.getExecutorThread().getStackTrace();
        for (StackTraceElement element : stack) {
            ...print it...
        }
    }
    

    【讨论】:

    • 感谢您的回复。这与我目前写的非常相似。
    【解决方案2】:

    你无法得到那个异常的踪迹。

    因为在那个异常中没有原因和被抑制的异常。

    【讨论】:

    • 您可以获得any异常的堆栈跟踪。问题是,超时异常没有关于池线程的任何信息,因为它没有发生在池线程中。它发生在主线程中。池线程中没有异常。当主线程变得不耐烦并放弃等待它完成时,池线程仍在愉快地运行。
    猜你喜欢
    • 2020-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-05
    • 2014-09-05
    • 2013-02-24
    • 2012-03-02
    • 2010-11-07
    相关资源
    最近更新 更多