Class ExecuteOnGetFutureTask<T>

  • Type Parameters:
    T - The result object type returned by this future
    All Implemented Interfaces:
    java.lang.Runnable, java.util.concurrent.Future<T>, java.util.concurrent.RunnableFuture<T>, CallableContainer<T>, ListenableFuture<T>, ListenableRunnableFuture<T>

    public class ExecuteOnGetFutureTask<T>
    extends ListenableFutureTask<T>
    This future task has a special ability to start execution in the thread requesting the get() IF it has not already started. It is still expected that this future will be provided to an executor, but if that executor has been unable to start execution by the time get() is requested, execution will start on the get() thread.

    This can make sense if for example you need to have the result of a given future before you can go forward with additional work. That way if the thread pool is too busy with other things, we can try to get the result for this work unit as fast as possible (once we are ready for it). If execution starts on the get() call, once the task is started in the thread pool, it will return immediately (WITHOUT invoking the task contained in the future).

    This does come with some details to be aware of. Execution may only occur on the get() request. Requesting Future.get(long, java.util.concurrent.TimeUnit) will NOT cause execution to start (as we can not ensure a timeout will be respected). In addition this can not work with recurring tasks.

    Since:
    2.4.0
    • Constructor Detail

      • ExecuteOnGetFutureTask

        public ExecuteOnGetFutureTask​(java.lang.Runnable task)
        Constructs a runnable future with a runnable work unit.
        Parameters:
        task - runnable to be run
      • ExecuteOnGetFutureTask

        public ExecuteOnGetFutureTask​(java.lang.Runnable task,
                                      T result)
        Constructs a runnable future with a runnable work unit.
        Parameters:
        task - runnable to be run
        result - result to be provide after run has completed
      • ExecuteOnGetFutureTask

        public ExecuteOnGetFutureTask​(java.util.concurrent.Callable<T> task)
        Constructs a runnable future with a callable work unit.
        Parameters:
        task - callable to be run
    • Method Detail

      • run

        public void run()
        Specified by:
        run in interface java.lang.Runnable
        Specified by:
        run in interface java.util.concurrent.RunnableFuture<T>
        Overrides:
        run in class ListenableFutureTask<T>
      • get

        public T get()
              throws java.lang.InterruptedException,
                     java.util.concurrent.ExecutionException
        Specified by:
        get in interface java.util.concurrent.Future<T>
        Throws:
        java.lang.InterruptedException
        java.util.concurrent.ExecutionException
      • getFailure

        public java.lang.Throwable getFailure()
                                       throws java.lang.InterruptedException
        Description copied from interface: ListenableFuture
        Similar to Future.get() except instead of providing a result, this will provide a thrown exception if ListenableFuture.isCompletedExceptionally() returns true. If the future has not completed yet this function will block until completion. If the future completed normally, this will return null.
        Specified by:
        getFailure in interface ListenableFuture<T>
        Returns:
        Throwable thrown in computing the future or null if completed normally
        Throws:
        java.lang.InterruptedException - If the current thread was interrupted while blocking
      • clearResult

        public void clearResult()
        Clears the stored result from this set future. This allows the result to be available for garbage collection. After this call, future calls to Future.get() will throw an IllegalStateException. So it is critical that this is only called after you are sure no future calls to get the result on this future will be attempted.

        The design of this is so that if you want to chain ListenableFuture's together, you can clear the results of old ones after their result has been consumed. This is really only useful in very specific instances.

        WARNING, this may produce some unexpected behaviors. For example if the result is being pulled while this is concurrently invoked a null result may be returned when a result was previously available. In addition Future.get() and ListenableFuture.callback(FutureCallback) attempt to reliably error in this condition but ListenableFuture.failureCallback(Consumer) and ListenableFuture.resultCallback(Consumer) do not. ListenableFuture.failureCallback(Consumer) will only show the unexpected clearResult state if the future had finished in a failure condition we can't report. And ListenableFuture.resultCallback(Consumer) will always be a no-op after clearing. In short BE CAUTIOUS, only use this if you are certain the result or failure wont be re-queried and you understand the risks.

      • cancel

        public boolean cancel​(boolean interrupt)
      • listener

        public ListenableFuture<T> listener​(java.lang.Runnable listener,
                                            java.util.concurrent.Executor executor,
                                            ListenableFuture.ListenerOptimizationStrategy optimize)
        Description copied from interface: ListenableFuture
        Add a listener to be called once the future has completed. If the future has already finished, this will be called immediately.

        If the provided Executor is null, the listener will execute on the thread which computed the original future (once it is done). If the future has already completed, the listener will execute immediately on the thread which is adding the listener.

        Caution should be used when choosing to optimize the listener execution. If the listener is complex, or wanting to be run concurrent, this optimization could prevent that. In addition it will prevent other listeners from potentially being invoked until it completes. However if the listener is small / fast, this can provide significant performance gains. It should also be known that not all ListenableFuture implementations may be able to do such an optimization. Please see ListenableFuture.ListenerOptimizationStrategy javadocs for more specific details of what optimizations are available.

        Parameters:
        listener - the listener to run when the computation is complete
        executor - Executor the listener should be ran on, or null
        optimize - true to avoid listener queuing for execution if already on the desired pool
        Returns:
        Exactly this instance to add more listeners or other functional operations
      • getRunningStackTrace

        public java.lang.StackTraceElement[] getRunningStackTrace()
        Description copied from interface: ListenableFuture
        A best effort to return the stack trace for for the executing thread of either this future, or a future which this depends on through the use of ListenableFuture.map(Function) or similar functions. If there is no thread executing the future yet, or the future has already completed, then this will return null.

        This is done without locking (though generating a stack trace still requires a JVM safe point), so the resulting stack trace is NOT guaranteed to be accurate. In most cases (particularly when blocking) this should be accurate though.

        Returns:
        The stack trace currently executing the future, or null if unavailable
      • isCancelled

        public boolean isCancelled()
      • isDone

        public boolean isDone()
      • isCompletedExceptionally

        public boolean isCompletedExceptionally()
        Description copied from interface: ListenableFuture
        Returns true if the future is both done and has completed with an error or was canceled. If this returns true the Throwable responsible for the error can be retrieved using ListenableFuture.getFailure();
        Returns:
        true if this ListenableFuture completed by a thrown Exception or was canceled
      • get

        public T get​(long timeout,
                     java.util.concurrent.TimeUnit unit)
              throws java.lang.InterruptedException,
                     java.util.concurrent.ExecutionException,
                     java.util.concurrent.TimeoutException
        Throws:
        java.lang.InterruptedException
        java.util.concurrent.ExecutionException
        java.util.concurrent.TimeoutException
      • getFailure

        public java.lang.Throwable getFailure​(long timeout,
                                              java.util.concurrent.TimeUnit unit)
                                       throws java.lang.InterruptedException,
                                              java.util.concurrent.TimeoutException
        Description copied from interface: ListenableFuture
        Similar to Future.get(long, TimeUnit) except instead of providing a result, this will provide a thrown exception if ListenableFuture.isCompletedExceptionally() returns true. If the future has not completed yet this function will block until completion. If the future completed normally, this will return null.
        Parameters:
        timeout - The maximum time to wait
        unit - The time unit of the timeout argument
        Returns:
        Throwable thrown in computing the future or null if completed normally
        Throws:
        java.lang.InterruptedException - If the current thread was interrupted while blocking
        java.util.concurrent.TimeoutException - If the timeout was reached before the future completed
      • callback

        public ListenableFuture<T> callback​(FutureCallback<? super T> callback,
                                            java.util.concurrent.Executor executor,
                                            ListenableFuture.ListenerOptimizationStrategy optimize)
        Description copied from interface: ListenableFuture
        Add a FutureCallback to be called once the future has completed. If the future has already finished, this will be called immediately.

        If the provided Executor is null, the callback will execute on the thread which computed the original future (once it is done). If the future has already completed, the callback will execute immediately on the thread which is adding the callback.

        Caution should be used when choosing to optimize the listener execution. If the listener is complex, or wanting to be run concurrent, this optimization could prevent that. In addition it will prevent other listeners from potentially being invoked until it completes. However if the listener is small / fast, this can provide significant performance gains. It should also be known that not all ListenableFuture implementations may be able to do such an optimization. Please see ListenableFuture.ListenerOptimizationStrategy javadocs for more specific details of what optimizations are available.

        If you only care about the success result case please see ListenableFuture.resultCallback(Consumer, Executor, ListenerOptimizationStrategy) or conversely if you only want to be invoked for failure cases please see ListenableFuture.failureCallback(Consumer, Executor, ListenerOptimizationStrategy).

        Parameters:
        callback - to be invoked when the computation is complete
        executor - Executor the callback should be ran on, or null
        optimize - true to avoid listener queuing for execution if already on the desired pool
        Returns:
        Exactly this instance to add more callbacks or other functional operations
      • resultCallback

        public ListenableFuture<T> resultCallback​(java.util.function.Consumer<? super T> callback,
                                                  java.util.concurrent.Executor executor,
                                                  ListenableFuture.ListenerOptimizationStrategy optimize)
        Description copied from interface: ListenableFuture
        Add a Consumer to be called once the future has completed. If the future has already finished, this will be called immediately. Assuming the future has completed without error, the result will be provided to the Consumer, otherwise it will go un-invoked.

        If the provided Executor is null, the callback will execute on the thread which computed the original future (once it is done). If the future has already completed, the callback will execute immediately on the thread which is adding the callback.

        Caution should be used when choosing to optimize the listener execution. If the listener is complex, or wanting to be run concurrent, this optimization could prevent that. In addition it will prevent other listeners from potentially being invoked until it completes. However if the listener is small / fast, this can provide significant performance gains. It should also be known that not all ListenableFuture implementations may be able to do such an optimization. Please see ListenableFuture.ListenerOptimizationStrategy javadocs for more specific details of what optimizations are available.

        Parameters:
        callback - to be invoked when the computation is complete
        executor - Executor the callback should be ran on, or null
        optimize - true to avoid listener queuing for execution if already on the desired pool
        Returns:
        Exactly this instance to add more callbacks or other functional operations
      • failureCallback

        public ListenableFuture<T> failureCallback​(java.util.function.Consumer<java.lang.Throwable> callback,
                                                   java.util.concurrent.Executor executor,
                                                   ListenableFuture.ListenerOptimizationStrategy optimize)
        Description copied from interface: ListenableFuture
        Add a Consumer to be called once the future has completed. If the future has already finished, this will be called immediately. Assuming the future has completed with an error, the Throwable will be provided to the Consumer, otherwise if no error occurred, the callback will go un-invoked.

        If the provided Executor is null, the callback will execute on the thread which computed the original future (once it is done). If the future has already completed, the callback will execute immediately on the thread which is adding the callback.

        Caution should be used when choosing to optimize the listener execution. If the listener is complex, or wanting to be run concurrent, this optimization could prevent that. In addition it will prevent other listeners from potentially being invoked until it completes. However if the listener is small / fast, this can provide significant performance gains. It should also be known that not all ListenableFuture implementations may be able to do such an optimization. Please see ListenableFuture.ListenerOptimizationStrategy javadocs for more specific details of what optimizations are available.

        Parameters:
        callback - to be invoked when the computation is complete
        executor - Executor the callback should be ran on, or null
        optimize - true to avoid listener queuing for execution if already on the desired pool
        Returns:
        Exactly this instance to add more callbacks or other functional operations
      • mapFailure

        public <TT extends java.lang.Throwable> ListenableFuture<T> mapFailure​(java.lang.Class<TT> throwableType,
                                                                               java.util.function.Function<? super TT,​? extends T> mapper)
        Description copied from interface: ListenableFuture
        Similar to ListenableFuture.throwMap(Function) except this mapper will only be invoked when the future is in a failure state (from either the original computation or an earlier mapper throwing an exception). If this future does resolve in a failure state, and that exception class matches the one provided here. The mapper function will then be provided that throwable, it can then map that throwable back into a result (perhaps an Optional), or re-throw either the same or a different exception keep the future in a failure state. If the future completes with a normal result, this mapper will be ignored, and the result will be forwarded on without invoking this mapper.
        Specified by:
        mapFailure in interface ListenableFuture<T>
        Type Parameters:
        TT - The type of throwable that should be handled
        Parameters:
        throwableType - The class referencing to the type of throwable this mapper handles
        mapper - The mapper to convert a thrown exception to either a result or thrown exception
        Returns:
        A ListenableFuture that will resolve after the mapper is considered
      • mapFailure

        public <TT extends java.lang.Throwable> ListenableFuture<T> mapFailure​(java.lang.Class<TT> throwableType,
                                                                               java.util.function.Function<? super TT,​? extends T> mapper,
                                                                               java.util.concurrent.Executor executor)
        Description copied from interface: ListenableFuture
        Similar to ListenableFuture.throwMap(Function, Executor) except this mapper will only be invoked when the future is in a failure state (from either the original computation or an earlier mapper throwing an exception). If this future does resolve in a failure state, and that exception class matches the one provided here. The mapper function will then be provided that throwable, it can then map that throwable back into a result (perhaps an Optional), or re-throw either the same or a different exception keep the future in a failure state. If the future completes with a normal result, this mapper will be ignored, and the result will be forwarded on without invoking this mapper.
        Specified by:
        mapFailure in interface ListenableFuture<T>
        Type Parameters:
        TT - The type of throwable that should be handled
        Parameters:
        throwableType - The class referencing to the type of throwable this mapper handles
        mapper - The mapper to convert a thrown exception to either a result or thrown exception
        executor - Executor to invoke mapper function on, or null to invoke on this thread or future complete thread (depending on future state)
        Returns:
        A ListenableFuture that will resolve after the mapper is considered
      • mapFailure

        public <TT extends java.lang.Throwable> ListenableFuture<T> mapFailure​(java.lang.Class<TT> throwableType,
                                                                               java.util.function.Function<? super TT,​? extends T> mapper,
                                                                               java.util.concurrent.Executor executor,
                                                                               ListenableFuture.ListenerOptimizationStrategy optimizeExecution)
        Description copied from interface: ListenableFuture
        Similar to ListenableFuture.throwMap(Function, Executor, ListenerOptimizationStrategy) except this mapper will only be invoked when the future is in a failure state (from either the original computation or an earlier mapper throwing an exception). If this future does resolve in a failure state, and that exception class matches the one provided here. The mapper function will then be provided that throwable, it can then map that throwable back into a result perhaps an Optional), or re-throw either the same or a different exception keep the future in a failure state. If the future completes with a normal result, this mapper will be ignored, and the result will be forwarded on without invoking this mapper.
        Specified by:
        mapFailure in interface ListenableFuture<T>
        Type Parameters:
        TT - The type of throwable that should be handled
        Parameters:
        throwableType - The class referencing to the type of throwable this mapper handles
        mapper - The mapper to convert a thrown exception to either a result or thrown exception
        executor - Executor to invoke mapper function on, or null to invoke on this thread or future complete thread (depending on future state)
        optimizeExecution - true to avoid listener queuing for execution if already on the desired pool
        Returns:
        A ListenableFuture that will resolve after the mapper is considered
      • flatMapFailure

        public <TT extends java.lang.Throwable> ListenableFuture<T> flatMapFailure​(java.lang.Class<TT> throwableType,
                                                                                   java.util.function.Function<? super TT,​ListenableFuture<T>> mapper)
        Description copied from interface: ListenableFuture
        Similar to ListenableFuture.mapFailure(Class, Function) except that this mapper function returns a ListenableFuture if it needs to map the Throwable / failure into a result or another failure. The mapper function can return a Future that will (or may) provide a result, or it can provide a future that will result in the same or another failure. Similar to ListenableFuture.mapFailure(Class, Function) the mapper can also throw an exception directly.
        Specified by:
        flatMapFailure in interface ListenableFuture<T>
        Type Parameters:
        TT - The type of throwable that should be handled
        Parameters:
        throwableType - The class referencing to the type of throwable this mapper handles
        mapper - Function to invoke in order to transform the futures result
        Returns:
        A ListenableFuture that will resolve after the mapper is considered
      • flatMapFailure

        public <TT extends java.lang.Throwable> ListenableFuture<T> flatMapFailure​(java.lang.Class<TT> throwableType,
                                                                                   java.util.function.Function<? super TT,​ListenableFuture<T>> mapper,
                                                                                   java.util.concurrent.Executor executor)
        Description copied from interface: ListenableFuture
        Similar to ListenableFuture.mapFailure(Class, Function, Executor) except that this mapper function returns a ListenableFuture if it needs to map the Throwable / failure into a result or another failure. The mapper function can return a Future that will (or may) provide a result, or it can provide a future that will result in the same or another failure. Similar to ListenableFuture.mapFailure(Class, Function, Executor) the mapper can also throw an exception directly.
        Specified by:
        flatMapFailure in interface ListenableFuture<T>
        Type Parameters:
        TT - The type of throwable that should be handled
        Parameters:
        throwableType - The class referencing to the type of throwable this mapper handles
        mapper - Function to invoke in order to transform the futures result
        executor - Executor to invoke mapper function on, or null to invoke on this thread or future complete thread (depending on future state)
        Returns:
        A ListenableFuture that will resolve after the mapper is considered