package de.invesdwin.util.concurrent; import java.lang.Thread.UncaughtExceptionHandler; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory; import java.util.concurrent.ForkJoinWorkerThread; import java.util.concurrent.atomic.AtomicInteger; import javax.annotation.Nonnull; import javax.annotation.concurrent.ThreadSafe; import de.invesdwin.util.assertions.Assertions; @ThreadSafe public class ConfiguredForkJoinWorkerThreadFactory implements ForkJoinWorkerThreadFactory { private final int threadpoolId = WrappedThreadFactory.THREADPOOL_IDS.incrementAndGet(); private final AtomicInteger threadIds = new AtomicInteger(); private final String name; public ConfiguredForkJoinWorkerThreadFactory(@Nonnull final String name) { Assertions.assertThat(name).isNotNull(); this.name = name; } @Override public ForkJoinWorkerThread newThread(final ForkJoinPool pool) { final String parentThreadName = Thread.currentThread().getName(); final ForkJoinWorkerThread t = new ForkJoinWorkerThread(pool) { /** * http://jsr166-concurrency.10961.n7.nabble.com/How-to-set-the-thread-group-of-the-ForkJoinPool-td1590.html */ @Override protected void onStart() { super.onStart(); final String curThreadName = threadpoolId + "-" + threadIds.incrementAndGet() + ":" + name; setName(curThreadName + Threads.NESTED_THREAD_NAME_SEPARATOR + parentThreadName); } }; /* * So that exceptions are still logged if runnables are sent into executors without futures being checked. This * keeps the default behaviour expected from normal threads. */ if (t.getUncaughtExceptionHandler() != Thread.getDefaultUncaughtExceptionHandler()) { throw new IllegalArgumentException( UncaughtExceptionHandler.class.getSimpleName() + " is not already set properly!"); } return t; } }