Ana*_*lov 12 java threadpool java-8 forkjoinpool
我试图找出如何在Java 8并行流中复制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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
哪个输出
Main Thread: MAIN
Parallel Consumer - 5: MAIN
Parallel Consumer - 4: MAIN
Parallel Consumer - 7: empty
Parallel Consumer - 3: empty
Parallel Consumer - 1: empty
Parallel Consumer - 6: empty
Parallel Consumer - 2: empty
Parallel Consumer - 0: MAIN
Run Code Online (Sandbox Code Playgroud)
有没有办法让我将main()方法中的ThreadLocal克隆到为每个并行执行生成的线程中?
这样我的结果就是:
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
Run Code Online (Sandbox Code Playgroud)
而不是第一个?
Sot*_*lis 11
正如路易斯在评论中所说的那样,你的例子很可能被简化为捕获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);
});
}
Run Code Online (Sandbox Code Playgroud)
从您的示例中可以看出,完整的用例是什么.
如果您确切知道将从主线程启动哪些线程,您可以考虑使用InheritableThreadLocal
此类扩展
ThreadLocal为提供从父线程到子线程的值的继承:当创建子线程时,子进程接收父对象具有值的所有可继承线程局部变量的初始值.
在你的情况下,宣布val作为InheritableThreadLocal,因为Thread对创建的实例parallel()中ForkJoinPool#commonPool()懒洋洋地创建,他们都从值继承set的main方法(和线程).
如果您在原始线程中设置值之前以某种方式使用commonPool(或parallel调用终端操作的任何池),则情况不会如此InhertiableThreadLocal.