In java, I would like to determine the current stack of the thread which populates the result of the future when a TimeoutException occurs. It seems that the top entry in the stack trace provided by a TimeoutException only indicates where future.get() was invoked, not the state of the background thread. For example:
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();
}
In this example I've found that the top entry is the future.get(1, TimeUnit.MILLISECONDS) entry, not the Thread.sleep(10000). I would like the stack trace to indicate Thread.sleep(10000) since this is what is currently being executed. Is there an elegant way of doing this?
I've found that if there is an actual execution problem, then the ExecutionException.printStackTrace() will indicate where the problem occurred in the background thread.
You can obtain a stack trace from a thread – by calling the getStackTrace method on that Thread instance. This invocation returns an array of StackTraceElement, from which details about stack frames of the thread can be extracted.
Another way to print stack trace is using the printStackTrace() method of the Throwable class. Just use new Throwable(). printStackTrace() method and it will print complete stack trace from where a method is called, into the console.
The stack trace, also called a backtrace, consists of a collection of stack records, which store an application's movement during its execution. The stack trace includes information about program subroutines and can be used to debug or troubleshoot and is often used to create log files.
If you had a reference, t, to the Thread was running the task, you could call t.getStackTrace()
; but the standard library ExecutorService implementations aren't going to tell you what thread is running the task.
You could have the task itself record what thread is running it:
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;
}
}
That way, when your main thread times out, it could call 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...
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With