package de.invesdwin.util.concurrent;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.Future;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.ThreadSafe;
import de.invesdwin.util.shutdown.IShutdownHook;
import de.invesdwin.util.shutdown.ShutdownHookManager;
@ThreadSafe
public class ConfiguredForkJoinPool extends ForkJoinPool {
private final IShutdownHook shutdownHook = new IShutdownHook() {
@Override
public void shutdown() throws Exception {
shutdownNow();
}
};
public ConfiguredForkJoinPool(@Nonnull final String name, final int parallelism, final boolean asyncMode) {
super(parallelism, new ConfiguredForkJoinWorkerThreadFactory(name), Thread.getDefaultUncaughtExceptionHandler(),
false);
configure();
}
private void configure() {
/*
* All executors should be shutdown on application shutdown.
*/
ShutdownHookManager.register(shutdownHook);
}
private void unconfigure() {
if (!isShutdown()) {
ShutdownHookManager.unregister(shutdownHook);
}
}
@Override
public void shutdown() {
super.shutdown();
unconfigure();
}
@Override
public List<Runnable> shutdownNow() {
final List<Runnable> l = super.shutdownNow();
unconfigure();
return l;
}
public boolean awaitTermination() throws InterruptedException {
return awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
}
public boolean awaitQuiescence() {
return awaitQuiescence(Long.MAX_VALUE, TimeUnit.DAYS);
}
@Override
public void execute(final ForkJoinTask<?> task) {
//cannot wrap this to update parent thread name
super.execute(task);
}
@Override
public void execute(final Runnable task) {
try {
super.execute(WrappedRunnable.newInstance(null, task));
} catch (final InterruptedException e) {
throw new RuntimeException(e);
}
}
@Override
public <T> ForkJoinTask<T> submit(final Callable<T> task) {
try {
return super.submit(WrappedCallable.newInstance(null, task));
} catch (final InterruptedException e) {
throw new RuntimeException(e);
}
}
@Override
public <T> ForkJoinTask<T> submit(final ForkJoinTask<T> task) {
//cannot wrap this to update parent thread name
return super.submit(task);
}
@Override
public ForkJoinTask<?> submit(final Runnable task) {
try {
return super.submit(WrappedRunnable.newInstance(null, task));
} catch (final InterruptedException e) {
throw new RuntimeException(e);
}
}
@Override
public <T> ForkJoinTask<T> submit(final Runnable task, final T result) {
try {
return super.submit(WrappedRunnable.newInstance(null, task), result);
} catch (final InterruptedException e) {
throw new RuntimeException(e);
}
}
@Override
public <T> T invoke(final ForkJoinTask<T> task) {
//cannot wrap this to update parent thread name
return super.invoke(task);
}
@Override
public <T> List<Future<T>> invokeAll(final Collection<? extends Callable<T>> tasks) {
try {
return super.invokeAll(WrappedCallable.newInstance(null, tasks));
} catch (final InterruptedException e) {
throw new RuntimeException(e);
}
}
@Override
public <T> List<Future<T>> invokeAll(final Collection<? extends Callable<T>> tasks, final long timeout,
final TimeUnit unit) throws InterruptedException {
return super.invokeAll(WrappedCallable.newInstance(null, tasks), timeout, unit);
}
@Override
public <T> T invokeAny(final Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException {
return super.invokeAny(WrappedCallable.newInstance(null, tasks));
}
@Override
public <T> T invokeAny(final Collection<? extends Callable<T>> tasks, final long timeout, final TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
return super.invokeAny(WrappedCallable.newInstance(null, tasks), timeout, unit);
}
@Override
protected <T> RunnableFuture<T> newTaskFor(final Callable<T> callable) {
try {
return super.newTaskFor(WrappedCallable.newInstance(null, callable));
} catch (final InterruptedException e) {
throw new RuntimeException(e);
}
}
@Override
protected <T> RunnableFuture<T> newTaskFor(final Runnable runnable, final T value) {
try {
return super.newTaskFor(WrappedRunnable.newInstance(null, runnable), value);
} catch (final InterruptedException e) {
throw new RuntimeException(e);
}
}
}