/**
* An implementation of ListeningExecutorService that attempts to detect deadlock scenarios that
* could occur if clients invoke the returned Future's <code>get</code> methods synchronously.
- * <p>
- * Deadlock scenarios are most apt to occur with a backing single-threaded executor where setting of
+ *
+ * <p>Deadlock scenarios are most apt to occur with a backing single-threaded executor where setting of
* the Future's result is executed on the single thread. Here's a scenario:
* <ul>
* <li>Client code is currently executing in an executor's single thread.</li>
* The second submitted task will never execute since the single thread is currently executing
* the client code which is blocked waiting for the submitted task to complete. Thus, deadlock has
* occurred.
- * <p>
- * This class prevents this scenario via the use of a ThreadLocal variable. When a task is invoked,
+ *
+ * <p>This class prevents this scenario via the use of a ThreadLocal variable. When a task is invoked,
* the ThreadLocal is set and, when a task completes, the ThreadLocal is cleared. Futures returned
* from this class override the <code>get</code> methods to check if the ThreadLocal is set. If it is,
* an ExecutionException is thrown with a custom cause.
*
- * Note that the ThreadLocal is not removed automatically, so some state may be left hanging off of
+ * <p>Note that the ThreadLocal is not removed automatically, so some state may be left hanging off of
* threads which have encountered this class. If you need to clean that state up, use
* {@link #cleanStateForCurrentThread()}.
*
}
@Override
- public void execute(final Runnable command) {
+ public void execute(@Nonnull final Runnable command) {
getDelegate().execute(wrapRunnable(command));
}
+ @Nonnull
@Override
public <T> ListenableFuture<T> submit(final Callable<T> task) {
return wrapListenableFuture(super.submit(wrapCallable(task)));
}
+ @Nonnull
@Override
public ListenableFuture<?> submit(final Runnable task) {
return wrapListenableFuture(super.submit(wrapRunnable(task)));
}
+ @Nonnull
@Override
public <T> ListenableFuture<T> submit(final Runnable task, final T result) {
return wrapListenableFuture(super.submit(wrapRunnable(task), result));
}
private Runnable wrapRunnable(final Runnable task) {
- return new Runnable() {
- @Override
- public void run() {
- final SettableBoolean b = primeDetector();
- try {
- task.run();
- } finally {
- b.reset();
- }
+ return () -> {
+ final SettableBoolean b = primeDetector();
+ try {
+ task.run();
+ } finally {
+ b.reset();
}
};
}
private <T> Callable<T> wrapCallable(final Callable<T> delagate) {
- return new Callable<T>() {
- @Override
- public T call() throws Exception {
- final SettableBoolean b = primeDetector();
- try {
- return delagate.call();
- } finally {
- b.reset();
- }
+ return () -> {
+ final SettableBoolean b = primeDetector();
+ try {
+ return delagate.call();
+ } finally {
+ b.reset();
}
};
}
}
@Override
- public T get(final long timeout, final TimeUnit unit)
+ public T get(final long timeout, @Nonnull final TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
checkDeadLockDetectorTL();
return super.get(timeout, unit);