Search code examples
javajava-8java.util.concurrent

How-to provide a ThreadLocal to CompletableFutures?


I need to provide a ThreadLocal to all the threads which end up running specific CompletableFuture.supplyAsync Suppliers.

From the javadoc I see that CompletableFuture uses "ForkJoinPool commonPool()" which very much fits my performance use case.

How do I transfer a ThreadLocal (and afterwards delete) to all pool threads running a specific CompletableFuture Supplier?

Remark:

I see that all CompletableFuture async completion methods accept an Executor. I would love to use the default ForkJoinPool commonPool() but if this is not possible I guess I have to override ThreadPoolExecutor and implement beforeExecute?


Solution

  • I guess you'll have to find your own way arround it as exec() on ForkJoinTask is protected. For concrete implementations you can of course write your own wrapper.

    This is what I would do for a single ThreadLocal and a Callable:

    public static class WithThreadLocal<V, T> implements Callable<V> {
        private final ThreadLocal<T> threadLocal;
        private final T              value;
        private final Callable<V>    callable;
    
    
        public WithThreadLocal(ThreadLocal<T> threadLocal, T value, Callable<V> callable) {
            this.threadLocal = threadLocal;
            this.value = value;
            this.callable = callable;
        }
    
        @Override
        public V call() throws Exception {
            T oldValue = threadLocal.get();
            try {
                threadLocal.set(value);
                return callable.call();
            } finally {
                threadLocal.set(oldValue);
            }
        }
    }
    

    From there you can use ForkJoinTask.adapt(). Otherwise you might be interrested in https://stackoverflow.com/a/7260332/1266906