2016-04-13 5 views
10

चलें कहते हैं कि हम कुछ इस तरह है:Do जावा 8 समानांतर धाराओं एक दृश्य के लिए एक ही धागे का उपयोग

LongStream.range(0, 10).parallel() 
.filter(l -> { 
    System.out.format("filter: %s [%s]\n", l, Thread.currentThread().getName()); 
    return l % 2 == 0; 
}) 
.map(l -> { 
    System.out.format("map: %s [%s]\n", l, Thread.currentThread().getName()); 
    return l; 
}); 

आप चलाते हैं इस कार्यक्रम के उत्पादन होगा कुछ की तरह:

filter: 6 [main] 
map: 6 [main] 
filter: 5 [main] 
filter: 4 [ForkJoinPool.commonPool-worker-2] 
map: 4 [ForkJoinPool.commonPool-worker-2] 
filter: 1 [ForkJoinPool.commonPool-worker-3] 
filter: 2 [ForkJoinPool.commonPool-worker-1] 
filter: 0 [ForkJoinPool.commonPool-worker-3] 
filter: 3 [ForkJoinPool.commonPool-worker-2] 
filter: 8 [main] 
filter: 7 [ForkJoinPool.commonPool-worker-2] 
filter: 9 [ForkJoinPool.commonPool-worker-2] 
map: 0 [ForkJoinPool.commonPool-worker-3] 
map: 2 [ForkJoinPool.commonPool-worker-1] 
map: 8 [main]` 

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

उत्तर

9

दुष्प्रभाव पर stream package summary अनुभाग से:

व्यवहार मापदंडों दुष्प्रभाव करते हैं, जब तक कि स्पष्ट रूप से कहा, वहाँ अन्य धागे के लिए उन दुष्प्रभाव की दृश्यता के रूप में कोई गारंटी नहीं है, न ही कोई गारंटी है कि एक ही धारा पाइपलाइन के भीतर "समान" तत्व पर विभिन्न संचालन एक ही थ्रेड में निष्पादित किए जाते हैं। राज्यविहीन परिचालन (जैसे filter, map, peek और flatMap) एकल संचालन जो चरणों एकल थ्रेड में क्रमिक रूप से करता है में एक साथ जुड़े हुए हैं:

4

यह नहीं संयोग है, यह कैसे स्ट्रीम API में इस समय OracleJDK/OpenJDK में कार्यान्वित किया जाता है है। हालांकि कुछ राज्यव्यापी संचालन शुरू करने से चीजें बदल सकती हैं। उदाहरण के लिए, एक limit जोड़ें:

LongStream.range(0, 10).parallel() 
.filter(l -> { 
    System.out.format("filter: %s [%s]\n", l, Thread.currentThread().getName()); 
    return l % 2 == 0; 
}) 
.limit(10) 
.map(l -> { 
    System.out.format("map: %s [%s]\n", l, Thread.currentThread().getName()); 
    return l; 
}) 
.forEach(x -> {}); 

अब सीमा एक बाधा जो दो भागों में पाइप लाइन विभाजन परिचय देता है। परिणाम इस तरह है:

filter: 8 [ForkJoinPool.commonPool-worker-2] 
filter: 9 [ForkJoinPool.commonPool-worker-7] 
filter: 0 [ForkJoinPool.commonPool-worker-6] 
filter: 1 [ForkJoinPool.commonPool-worker-3] 
filter: 4 [ForkJoinPool.commonPool-worker-5] 
filter: 2 [ForkJoinPool.commonPool-worker-1] 
filter: 6 [main] 
filter: 7 [ForkJoinPool.commonPool-worker-4] 
filter: 3 [ForkJoinPool.commonPool-worker-6] 
filter: 5 [ForkJoinPool.commonPool-worker-2] 
map: 0 [ForkJoinPool.commonPool-worker-6] 
map: 2 [ForkJoinPool.commonPool-worker-2] 
map: 8 [ForkJoinPool.commonPool-worker-4] 
map: 6 [main] 
map: 4 [ForkJoinPool.commonPool-worker-6] 

देखें कि तत्व # 2 FJP -1 सूत्र में फ़िल्टर किया गया था, लेकिन मैप किया FJP -2 सूत्र में।

ध्यान दें कि @ मिशा ने सही तरीके से उद्धृत किया है, यहां तक ​​कि स्टेटलेस ऑपरेशंस के लिए भी कोई गारंटी नहीं है कि एक ही थ्रेड का उपयोग किया जाएगा। यह संभव है कि भविष्य या वैकल्पिक स्ट्रीम एपीआई कार्यान्वयन इस व्यवहार को बदल देगा (उदाहरण के लिए, निर्माता-उपभोक्ता दृष्टिकोण का उपयोग करना)।

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