2015-11-25 11 views
8

मैं यह पता लगाने की कोशिश कर रहा हूं कि मैं जावा 8 समानांतर स्ट्रीम में थ्रेडलोकल मान कैसे कॉपी कर सकता हूं।जावा 8 समांतर स्ट्रीम और थ्रेडलोकल

हम इस पर विचार तो अगर यह:

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 
बजाय पहले एक की

?

+3

मुझे उम्मीद नहीं होगी। लेकिन यह पहली जगह में केवल 'थ्रेडलोकल' क्यों है, बस अपनी मुख्य विधि में बनाए गए और फिर स्पष्ट रूप से लैम्ब्डा को पारित किया गया? –

+4

क्या आप धाराओं को पार करने की कोशिश कर रहे हैं? मैंने सुना है कि यह बुरा होगा। – zapl

उत्तर

7

As Louis has stated in the comments, अपने उदाहरण बहुत अच्छी तरह से लैम्ब्डा अभिव्यक्ति

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 उदाहरणों lazily बनाई गई हैं के बाद से, वे सब main विधि (और धागा) में मूल्य set से विरासत होगा।

इस मामले में अगर आप किसी भी तरह से उपयोग नहीं किया होगा commonPool (या जो भी पूल parallel टर्मिनल संचालन पर कहा जाता था) इससे पहले कि आप मूल सूत्र में InhertiableThreadLocal मान सेट करें।

+0

हां, मेरा उदाहरण उपयोग के मामले के बारे में बहुत अधिक जानकारी नहीं दे रहा था। वास्तविक उपयोग केस कुछ अन्य कोड (समांतर() उपभोक्ता के अलावा) के साथ है और थ्रेडलोकल को सर्वलेट फ़िल्टर में पॉप्युलेट किया जा रहा है और फिर स्प्रिंग एमवीसी नियंत्रक में उपयोग किया जाता है, और कुछ बार बोर्ड में विभिन्न रननेबल कार्यान्वयन के लिए क्लोन किया जाता है (सेवा कॉल, आदि)। तो सड़क के नीचे विभिन्न कॉल होंगे जो ThreadContext.get (कुछ) हैं। इनहेरटेबल थ्रेडलोकल को समझाने के लिए धन्यवाद, मैं इसे आज़मा दूंगा! –

संबंधित मुद्दे