java - 如何在TimeoutException上获得未来的堆栈跟踪

时间:2014-12-18 18:00:58

标签: java multithreading executorservice

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

在这个例子中,我发现top条目是future.get(1,TimeUnit.MILLISECONDS)条目,而不是Thread.sleep(10000)。我希望堆栈跟踪指示Thread.sleep(10000),因为这是当前正在执行的内容。这样做有一种优雅的方式吗?

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

3 个答案:

答案 0 :(得分:4)

如果你有一个引用,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...
    }
}

答案 1 :(得分:0)

你无法获得该异常的痕迹。

因为在该异常中没有原因和抑制异常。

答案 2 :(得分:0)

堆栈跟踪在执行期间中断是否意味着我的手机正在被监视 n 它在有人从另一台计算机上在我的手机上执行的跟踪中间中断?我对此并不熟悉,只是在我的手机上加载了 vpn 卡巴斯基,这出现在我的通知中。 .juat 试图理解这些东西