簡體   English   中英

Java 8 並行流和 ThreadLocal

[英]Java 8 parallel stream and ThreadLocal

我想弄清楚如何在 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);
            }
        }
    }

哪些輸出

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

有沒有辦法讓我將 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

而不是第一個?

正如路易斯在評論中所述,您的示例可以很好地簡化為捕獲 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);
    });
}

從您的示例中看不出完整的用例是什么。

如果您確切知道將從主線程啟動哪些線程,則可以考慮使用InheritableThreadLocal

此類擴展ThreadLocal以提供從父線程到子線程的值繼承:當創建子線程時,子線程接收父線程具有值的所有可繼承線程局部變量的初始值。

在您的情況下,將val聲明為InheritableThreadLocal ,因為在ForkJoinPool#commonPool()中為parallel()創建的Thread實例是惰性創建的,它們都將從main方法(和線程)中set的值繼承。

如果您在原始線程中設置InhertiableThreadLocal值之前以某種方式使用了commonPool (或調用parallel終端操作的任何池),則情況InhertiableThreadLocal

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM