/** * Constructs a runnable future with a runnable work unit. * * @param recurring boolean to indicate if this task can run multiple times, and thus must be reset after each run * @param task runnable to be run * @param result result to be provide after run has completed * @param executingExecutor Executor task will be run on for possible listener optimization, or {@code null} */ public ListenableFutureTask(boolean recurring, Runnable task, T result, Executor executingExecutor) { this(recurring, RunnableCallableAdapter.adapt(task, result), executingExecutor); }
@Test public void getContainedRunnableTest() { TestRunnable tr = new TestRunnable(); RunnableCallableAdapter<?> rca = (RunnableCallableAdapter<?>)RunnableCallableAdapter.adapt(tr, null); assertTrue(tr == rca.getContainedRunnable()); }
public List<Pair<Runnable, StackTraceElement[]>> getLongRunningTasks(long durationLimitMillis) { List<Pair<Runnable, StackTraceElement[]>> result = new ArrayList<>(); if (accurateTime) { // ensure clock is updated before loop Clock.accurateForwardProgressingMillis(); } for (Map.Entry<Pair<Thread, TaskStatWrapper>, Long> e : runningTasks.entrySet()) { if (Clock.lastKnownForwardProgressingMillis() - e.getValue() > durationLimitMillis) { Runnable task = e.getKey().getRight().task; if (task instanceof ListenableFutureTask) { ListenableFutureTask<?> lft = (ListenableFutureTask<?>)task; if (lft.getContainedCallable() instanceof RunnableCallableAdapter) { RunnableCallableAdapter<?> rca = (RunnableCallableAdapter<?>)lft.getContainedCallable(); task = rca.getContainedRunnable(); } } StackTraceElement[] stack = e.getKey().getLeft().getStackTrace(); // verify still in collection after capturing stack if (runningTasks.containsKey(e.getKey())) { result.add(new Pair<>(task, stack)); } } } return result; }
/** * Adapt a {@link Runnable} and result into a {@link Callable}. The returned callable will * invoke {@link Runnable#run()} then return the result provided to this function. * * @param <T> Type of result to be returned from provided {@link Callable} * @param runnable Runnable to be invoked when this adapter is ran * @param result Result to return from Callable or {@code null} * @return A {@link Callable} instance for invocation */ @SuppressWarnings("unchecked") public static <T> Callable<T> adapt(Runnable runnable, T result) { if (runnable == DoNothingRunnable.instance()) { if (result == null) { return (Callable<T>) DoNothingCallable.INSTANCE; } else { return () -> result; } } else { return new RunnableCallableAdapter<>(runnable, result); } }
public List<Pair<Runnable, StackTraceElement[]>> getLongRunningTasks(long durationLimitMillis) { List<Pair<Runnable, StackTraceElement[]>> result = new ArrayList<>(); if (accurateTime) { // ensure clock is updated before loop Clock.accurateForwardProgressingMillis(); } for (Map.Entry<Pair<Thread, TaskStatWrapper>, Long> e : runningTasks.entrySet()) { if (Clock.lastKnownForwardProgressingMillis() - e.getValue() > durationLimitMillis) { Runnable task = e.getKey().getRight().task; if (task instanceof ListenableFutureTask) { ListenableFutureTask<?> lft = (ListenableFutureTask<?>)task; if (lft.getContainedCallable() instanceof RunnableCallableAdapter) { RunnableCallableAdapter<?> rca = (RunnableCallableAdapter<?>)lft.getContainedCallable(); task = rca.getContainedRunnable(); } } StackTraceElement[] stack = e.getKey().getLeft().getStackTrace(); // verify still in collection after capturing stack if (runningTasks.containsKey(e.getKey())) { result.add(new Pair<>(task, stack)); } } } return result; }
/** * Adapt a {@link Runnable} and result into a {@link Callable}. The returned callable will * invoke {@link Runnable#run()} then return the result provided to this function. * * @param <T> Type of result to be returned from provided {@link Callable} * @param runnable Runnable to be invoked when this adapter is ran * @param result Result to return from Callable or {@code null} * @return A {@link Callable} instance for invocation */ @SuppressWarnings("unchecked") public static <T> Callable<T> adapt(Runnable runnable, T result) { if (runnable == DoNothingRunnable.instance()) { if (result == null) { return (Callable<T>) DoNothingCallable.INSTANCE; } else { return () -> result; } } else { return new RunnableCallableAdapter<>(runnable, result); } }
/** * Constructs a runnable future with a runnable work unit. * * @param recurring boolean to indicate if this task can run multiple times, and thus must be reset after each run * @param task runnable to be run * @param result result to be provide after run has completed * @param executingExecutor Executor task will be run on for possible listener optimization, or {@code null} */ public ListenableFutureTask(boolean recurring, Runnable task, T result, Executor executingExecutor) { this(recurring, RunnableCallableAdapter.adapt(task, result), executingExecutor); }
@Override public List<Pair<Runnable, StackTraceElement[]>> getLongRunningTasks(long durationLimitMillis) { List<Pair<Runnable, StackTraceElement[]>> result = new ArrayList<>(); if (statsContainer.accurateTime) { // ensure clock is updated before loop Clock.accurateForwardProgressingMillis(); } for (Map.Entry<Pair<Thread, Runnable>, Long> e : statsContainer.runningTasks.entrySet()) { if (Clock.lastKnownForwardProgressingMillis() - e.getValue() > durationLimitMillis) { Runnable task = e.getKey().getRight(); if (task instanceof ListenableFutureTask) { ListenableFutureTask<?> lft = (ListenableFutureTask<?>)task; if (lft.getContainedCallable() instanceof RunnableCallableAdapter) { RunnableCallableAdapter<?> rca = (RunnableCallableAdapter<?>)lft.getContainedCallable(); task = rca.getContainedRunnable(); } } StackTraceElement[] stack = e.getKey().getLeft().getStackTrace(); // verify still in collection after capturing stack if (statsContainer.runningTasks.containsKey(e.getKey())) { result.add(new Pair<>(task, stack)); } } } return result; }
@SuppressWarnings({ "unused", "deprecation" }) @Test (expected = IllegalArgumentException.class) public void constructorFail() { new RunnableCallableAdapter<>(null); fail("Exception should have thrown"); }
@Override public <T> ListenableFuture<T> submitScheduled(Runnable task, T result, long delayInMs, TaskPriority priority) { return submitScheduled(RunnableCallableAdapter.adapt(task, result), delayInMs, priority); }
@Override public List<Pair<Runnable, StackTraceElement[]>> getLongRunningTasks(long durationLimitMillis) { List<Pair<Runnable, StackTraceElement[]>> result = new ArrayList<>(); if (statsContainer.accurateTime) { // ensure clock is updated before loop Clock.accurateForwardProgressingMillis(); } for (Map.Entry<Pair<Thread, Runnable>, Long> e : statsContainer.runningTasks.entrySet()) { if (Clock.lastKnownForwardProgressingMillis() - e.getValue() > durationLimitMillis) { Runnable task = e.getKey().getRight(); if (task instanceof ListenableFutureTask) { ListenableFutureTask<?> lft = (ListenableFutureTask<?>)task; if (lft.getContainedCallable() instanceof RunnableCallableAdapter) { RunnableCallableAdapter<?> rca = (RunnableCallableAdapter<?>)lft.getContainedCallable(); task = rca.getContainedRunnable(); } } StackTraceElement[] stack = e.getKey().getLeft().getStackTrace(); // verify still in collection after capturing stack if (statsContainer.runningTasks.containsKey(e.getKey())) { result.add(new Pair<>(task, stack)); } } } return result; }
@Override public <T> ListenableFuture<T> submitScheduled(Runnable task, T result, long delayInMs, TaskPriority priority) { return submitScheduled(RunnableCallableAdapter.adapt(task, result), delayInMs, priority); }
/** * Submit a task to be run with a given thread key. * * @param <T> type of result returned from the future * @param threadKey object key where {@code equals()} will be used to determine execution thread * @param task Runnable to be executed * @param result Result to be returned from future when task completes * @return Future to represent when the execution has occurred and provide the given result */ public <T> ListenableFuture<T> submit(Object threadKey, Runnable task, T result) { return submit(threadKey, RunnableCallableAdapter.adapt(task, result)); }
/** * Submit a task to be run with a given thread key. * * @param <T> type of result returned from the future * @param threadKey object key where {@code equals()} will be used to determine execution thread * @param task Runnable to be executed * @param result Result to be returned from future when task completes * @return Future to represent when the execution has occurred and provide the given result */ public <T> ListenableFuture<T> submit(Object threadKey, Runnable task, T result) { return submit(threadKey, RunnableCallableAdapter.adapt(task, result)); }
@Override public <T> ListenableFuture<T> submitScheduled(Runnable task, T result, long delayInMs, TaskPriority priority) { return submitScheduled(RunnableCallableAdapter.adapt(task, result), delayInMs, priority); }
@Override public <T> ListenableFuture<T> submitScheduled(Runnable task, T result, long delayInMs, TaskPriority priority) { return submitScheduled(RunnableCallableAdapter.adapt(task, result), delayInMs, priority); }
@Override public <T> ListenableFuture<T> submitScheduled(Runnable task, T result, long delayInMs, TaskPriority priority) { return submitScheduled(RunnableCallableAdapter.adapt(task, result), delayInMs, priority); }
@Override public <T> ListenableFuture<T> submitScheduled(Runnable task, T result, long delayInMs, TaskPriority priority) { return submitScheduled(RunnableCallableAdapter.adapt(task, result), delayInMs, priority); }
@Override public <T> ListenableFuture<T> submit(Runnable task, T result) { return submit(RunnableCallableAdapter.adapt(task, result)); }