Java 8并行流和ThreadLocal

Java 8并行流和ThreadLocal,java,java-8,threadpool,forkjoinpool,Java,Java 8,Threadpool,Forkjoinpool,我试图弄清楚如何在Java8并行流中复制ThreadLocal值 如果我们考虑这一点: public class ThreadLocalTest { public static void main(String[] args) { ThreadContext.set("MAIN"); System.out.printf("Main Thread: %s\n", ThreadContext.get());

我试图弄清楚如何在Java8并行流中复制ThreadLocal值

如果我们考虑这一点:

    public class ThreadLocalTest {

        public static void main(String[] args)  {
            ThreadContext.set("MAIN");
            System.out.printf("Main Thread: %s\n", ThreadContext.get());

            IntStream.range(0,8).boxed().parallel().forEach(n -> {
                System.out.printf("Parallel Consumer - %d: %s\n", n, ThreadContext.get());
            });
        }

        private static class ThreadContext {
            private static ThreadLocal<String> val = ThreadLocal.withInitial(() -> "empty");

            public ThreadContext() {
            }

            public static String get() {
                return val.get();
            }

            public static void set(String x) {
                ThreadContext.val.set(x);
            }
        }
    }
有没有办法将ThreadLocal from main()方法克隆到为每次并行执行生成的线程中

因此,我的结果是:

Main Thread: MAIN
Parallel Consumer - 5: MAIN
Parallel Consumer - 4: MAIN
Parallel Consumer - 7: MAIN
Parallel Consumer - 3: MAIN
Parallel Consumer - 1: MAIN
Parallel Consumer - 6: MAIN
Parallel Consumer - 2: MAIN
Parallel Consumer - 0: MAIN
您的示例可以很好地简化为在lambda表达式中捕获局部变量的值,而不是第一个

public static void main(String[] args)  {
    String value = "MAIN";
    System.out.printf("Main Thread: %s\n", value);

    IntStream.range(0,8).boxed().parallel().forEach(n -> {
        System.out.printf("Parallel Consumer - %d: %s\n", n, value);
    });
}
从您的示例来看,完整用例是什么并不明显

如果您确切知道从主线程中的哪些线程将是“强>开始< /强>,您可以考虑使用

该类扩展了
ThreadLocal
,以提供从 父线程到子线程:创建子线程时 子线程接收所有可继承线程本地的初始值 父项具有值的变量

在您的例子中,将
val
声明为
heritableThreadlocal
,因为在
ForkJoinPool#commonPool()
中为
parallel()
创建的
Thread
实例是惰性创建的,它们都将继承自
main
方法(和线程)中的值
set


如果在原始线程中设置
InheritableThreadlocal
值之前,您以某种方式使用了
commonPool
(或调用
并行
终端操作的任何池),则不会出现这种情况。

。但是,为什么这个
ThreadLocal
首先不是在主方法中创建,然后显式地传递给lambda?您是否在尝试跨流?我听说这会很糟糕。是的,我的例子没有给出太多关于用例的信息。实际用例与其他一些代码(parallel()使用者除外)一起使用,ThreadLocal被填充到Servlet过滤器中,然后在Spring MVC控制器中使用,有时被克隆用于各种可运行的实现(服务调用等)。因此,今后将有各种调用,它们是ThreadContext.get(something)。感谢您解释InheritableThreadLocal,我将尝试一下!
public static void main(String[] args)  {
    String value = "MAIN";
    System.out.printf("Main Thread: %s\n", value);

    IntStream.range(0,8).boxed().parallel().forEach(n -> {
        System.out.printf("Parallel Consumer - %d: %s\n", n, value);
    });
}