[concurrency-interest] Enhance TimeoutException to include more details

Jason Mehrens jason_mehrens at hotmail.com
Thu Dec 10 13:26:40 EST 2015


Hello Concurrency-interest,

A lot of the synchronizers included in jsr166 that throw TimeoutException do not include the information that is useful to know when such an event occurs. I'm assuming that performance, keeping the code simple, and not crippling evolution of the code are the main drivers for the way it is today.

With those goals in mind, could TimeoutException be modified to include:
1. Information about the timeout value with a time unit mapped to getMessage().
2. A cause Throwable that contained the current stacktrace of the 'owner' thread (ASQ.getExclusiveOwnerThread().getStackTrace()).
3. Suppressed exceptions that contained all of the threads waiting to acquire (ASQ.getQueuedThreads())


For example, if take a FutureTask with 4 threads:
1. A thread calls FutureTask.run
2. Two threads call FutureTask.get.
3. One thread calls FutureTask.get(1, SECONDS) and logs the timeout.


To convert the stacktraces to a Throwable I abused the IllegalStateException for a proof of concept (no security manager).
The timeout could be described using the following (hopefully the formatting works).

=================================================================================
java.util.concurrent.TimeoutException: 1 SECONDS
    at java.util.concurrent.FutureTask.get(FutureTask.java:205)
    at TimeoutExampleOutput.testFutureTask(TimeoutExampleOutput.java:46)
    at TimeoutExampleOutput.main(TimeoutExampleOutput.java:12)
    Suppressed: java.lang.IllegalStateException: [14-WAITING-Thread[pool-1-thread-2,5,main]]
        at sun.misc.Unsafe.park(Native Method)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:429)
        at java.util.concurrent.FutureTask.get(FutureTask.java:191)
        at TimeoutExampleOutput$2.run(TimeoutExampleOutput.java:37)
        at java.lang.Thread.run(Thread.java:745)
    Suppressed: java.lang.IllegalStateException: [15-WAITING-Thread[pool-1-thread-3,5,main]]
        at sun.misc.Unsafe.park(Native Method)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:429)
        at java.util.concurrent.FutureTask.get(FutureTask.java:191)
        at TimeoutExampleOutput$2.run(TimeoutExampleOutput.java:37)
        at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: [13-TIMED_WAITING-Thread[pool-1-thread-1,5,main]]
    at java.lang.Thread.sleep(Native Method)
    at TimeoutExampleOutput$1.call(TimeoutExampleOutput.java:19)
    at TimeoutExampleOutput$1.call(TimeoutExampleOutput.java:16)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.lang.Thread.run(Thread.java:745)
==================================================================================

The state of all 4 threads is described in this one failure.  You can see that this thread timed out was caused by the worker taking a nap and everyone else is being held up because of it.

I would assume there is a way to capture some of this state in TimeoutException and then delay the evaluation of that state until some TimeoutException method is called like getCause or getMessage and retain most of the performance goals.  Or perhaps adding a method to TimeoutException to opt into this information.

Any thoughts on this?

Regards,

Jason



More information about the Concurrency-interest mailing list