प्रत्येक अनुरोध आइटम के लिए कई थ्रेड कैसे बनाएँ


9

मैं आदेश स्तर पर मल्टीथ्रेडिंग का उपयोग करके नीचे दिए गए कोड को संसाधित करने का प्रयास कर रहा हूं।

List<String> orders = Arrays.asList("order1", "order2", 
                   "order3", "order4", "order1");

वर्तमान अनुक्रमिक निष्पादन:

orders.stream().forEach(order -> {
    rules.forEach(rule -> {
        finalList.add(beanMapper.getBean(rule)
                .applyRule(createTemplate.apply(getMetaData.apply(rule), command),
                           order));
    });
});

मैंने प्रयोग करने की कोशिश की है:

orders.parallelStream().forEach(order -> {}} // code snippet.

लेकिन यह नियमों को बदल रहा है। प्रत्येक नियम (नियम -> {}} आदेश।

उदाहरण के लिए:
इनपुट:

 List<String> orders = Arrays.asList("order1", "order2", 
                         "order3", "order4", "order1");
 List<String> rules = Arrays.asList("rule1", "rule2", "rule3");

अपेक्षित उत्पादन:

order1 with rule1, rule2, rule3
order2 with rule1, rule2, rule3

इसके साथ वास्तविक उत्पादन parallelStream():

order1 with rule3, rule1, rule2
order1 with rule2, rule1, rule3

मैं आदेश के आदेश के बारे में परेशान नहीं हूं, लेकिन मैं नियमों के एह क्रम के बारे में परेशान हूं । आदेश किसी भी क्रम में प्रक्रिया कर सकते हैं, लेकिन नियमों को प्रत्येक आदेश के लिए उसी क्रम में निष्पादित किया जाना चाहिए।

कृपया मदद कीजिए।

जवाबों:


4

आप उपयोग कर सकते हैं :

orders.stream().parallel().forEachOrdered(// Your rules logic goes here. )

स्ट्रीम के आदेश को बनाए रखने के लिए ForEachOrdered गारंटी।

तो आपके संदर्भ के लिए:

orders.stream().parallel().forEachOrdered( order -> {

            rules.stream().parallel().forEachOrdered ( rule -> {

                 System.out.println( " Order : " + order + " rule :" + rule);
            });

        });

ध्यान दें : जबकि हम ऐसा कर सकते हैं, प्रदर्शन को बारीकी से देखा जाना चाहिए क्योंकि परलोकवाद और आदेश एक दूसरे से बहुत अच्छी तरह से शादी नहीं करते हैं!

उत्पादन

 Order : order1 rule :rule1
 Order : order1 rule :rule2
 Order : order1 rule :rule3
 Order : order2 rule :rule1
 Order : order2 rule :rule2
 Order : order2 rule :rule3
 Order : order3 rule :rule1
 Order : order3 rule :rule2
 Order : order3 rule :rule3
 Order : order4 rule :rule1
 Order : order4 rule :rule2
 Order : order4 rule :rule3
 Order : order1 rule :rule1
 Order : order1 rule :rule2
 Order : order1 rule :rule3

जवाब के लिए धन्यवाद। forEachOrdered स्ट्रीम के ऑर्डर की गारंटी देता है, लेकिन फिर यह प्रदर्शन को धीमा कर देता है। मैंने इसकी कोशिश की और आवेदन क्रमिक प्रसंस्करण के समान समय ले रहा है। धारा ()। समानांतर और forEachOrdered एक दूसरे की प्रशंसा नहीं करता है।
मयंक बिष्ट

हाँ, मैं मानता हूँ कि हमें ऐसा करने से पहले पूर्ण विलंबता विश्लेषण करने की आवश्यकता है।
प्रमोद एस। निकम

हाँ, मुझे इसका उपयोग करने के लिए समान प्रदर्शन मिल रहा है, कोई सुधार नहीं हुआ है।
मयंक बिष्ट

1
ऐसा करने के लिए बेहतर समाधान पाने के लिए इस धागे का बारीकी से पालन करें।
प्रमोद एस। निकम

क्या मैं ExecutorService का उपयोग करके समानांतर प्रसंस्करण प्राप्त कर सकता हूं?
मयंक बिष्ट

1

आप finalListएक ही समय में विभिन्न थ्रेड्स से तत्व जोड़ते हैं । यह नियमों को अलग-अलग आदेशों में लागू करने के परिणामों को मिला रहा है (नियमों को उनके आदेश द्वारा समूहीकृत नहीं किया जा रहा है)।

आप इसे प्रत्येक के लिए एक अस्थायी सूची बनाकर ठीक कर सकते हैं orderऔर फिर सभी अस्थायी सूचियों को एक में विलय कर सकते हैं finalList

यहाँ आप इसे स्ट्रीम-एपीआई (जावा 9+) का उपयोग करके कैसे कर सकते हैं:

List<AppliedRule> finalList = orders.parallelStream().map(order ->
        rules.stream().map(rule -> applyRule(order, rule)).collect(Collectors.toList())
).collect(Collectors.flatMapping(Collection::stream, Collectors.toList()));

नोट: स्ट्रीम संग्रह के दौरान समतल मैपिंग को Collectors.flatMapping()सरलता flatMapसे चलाने के बजाय यहाँ उपयोग किया जाता है ।


जावा 8 एनालॉग:

List<AppliedRule> finalList = orders.parallelStream().map(order ->
        rules.stream().map(rule -> applyRule(order, rule)).collect(Collectors.toList())
).collect(Collectors.toList())
        .stream()
        .flatMap(Collection::stream)
        .collect(Collectors.toList());

जवाब के लिए धन्यवाद। मैंने आपके दृष्टिकोण की कोशिश की और मुझे java.util मिल रहा है। CCcurrentModificationException: null
mayank bisht

FinalList = order.parallelStream () (.map (आदेश -> rules.stream) (.map (नियम -> beanMapper.getBean (नियम)) .applyRule (createTemplate.apply (getetaData.apply (नियम), कमांड), आदेश))। .collect (Collectors.toList ())) कलेक्ट (Collectors.toList ()) धारा () flatMap (संग्रह :: स्ट्रीम) .collect (Collectors.toList (।))।।
मयंक बिष्ट

@mayankbisht, इसका मतलब है कि beanMapper.getBean(rule) .applyRule(createTemplate.apply(getMetaData.apply(rule), command), order)यह एक शुद्ध कार्य नहीं है, इसलिए इसका उपयोग समानांतर में नहीं किया जा सकता है। इससे सभी दुष्प्रभावों को हटाने की कोशिश करें; ConcurrentModificationExceptionस्टैक ट्रेस उन्हें खोजने में मदद कर सकता है।
बनानून

0

यह काम करेगा?

final int rulesSize = rules.size();
AtomicInteger atomicInteger = new AtomicInteger(0);
orders.stream().parallel().forEach(order -> {
    IntStream.range(0, rulesSize).parallel().forEach( i -> {
        synchronized (atomicInteger) {
            System.out.println(" Order : " + order + " rule :" + rules.get(atomicInteger.getAndIncrement() % rulesSize));
        }
    });
});

उत्पादन

 Order : order1 rule :rule1
 Order : order4 rule :rule2
 Order : order1 rule :rule3
 Order : order3 rule :rule1
 Order : order3 rule :rule2
 Order : order3 rule :rule3
 Order : order2 rule :rule1
 Order : order2 rule :rule2
 Order : order2 rule :rule3
 Order : order1 rule :rule1
 Order : order1 rule :rule2
 Order : order4 rule :rule3
 Order : order1 rule :rule1
 Order : order4 rule :rule2
 Order : order1 rule :rule3

0

आदेशों का क्रम कुछ भी हो सकता है, लेकिन नियमों का क्रम नहीं बदलना चाहिए। इसके अलावा एक विशेष आदेश के लिए नियम एक समूह में आना चाहिए।

यदि ऐसा है, तो वास्तविक समानता के लिए कोई जगह नहीं है।

कब

order1-rule1
order1-rule2
order2-rule1
order2-rule2

तथा

order2-rule1
order2-rule2
order1-rule1
order1-rule2

2 आदेशों और 2 नियमों के लिए केवल वैध रन हैं,
और

order1-rule1
order2-rule1
order1-rule2
order2-rule2

अवैध माना जाता है, यह समानता नहीं है, बस यादृच्छिककरण है order, संभवतः लाभ के बिना। यदि आप order1हर समय पहले आने के साथ "ऊब" रहे हैं , तो आप सूची में फेरबदल कर सकते हैं, लेकिन यह सब है:

public static void main (String[] args) throws java.lang.Exception
{
    List<String> orders = Arrays.asList("order1", "order2", "order3", "order4");
    List<String> rules = Arrays.asList("rule1", "rule2", "rule3");
    Collections.shuffle(orders);
    orders.forEach(order->{
        rules.forEach(rule->{
            System.out.println(order+"-"+rule);
        });
    });
}

स्ट्रीमिंग भी आवश्यक नहीं है, बस दो नेस्टेड छोरों। टेस्ट: https://ideone.com/qI3dqd

order2-rule1
order2-rule2
order2-rule3
order4-rule1
order4-rule2
order4-rule3
order1-rule1
order1-rule2
order1-rule3
order3-rule1
order3-rule2
order3-rule3


मूल उत्तर

लेकिन यह नियमों को बदल रहा है। प्रत्येक नियम (नियम -> {}} आदेश।

नहीं, यह नहीं है। orderरों ओवरलैप हो सकता है, लेकिन के आदेश ruleप्रत्येक आदेश के लिए रों रखा जाता है। एक गैर-समानांतर क्यों होगाforEach कुछ और ?

उदाहरण कोड:

public static void main (String[] args) throws java.lang.Exception
{
    List<String> orders = Arrays.asList("order1", "order2", "order3", "order4");
    List<String> rules = Arrays.asList("rule1", "rule2", "rule3");
    orders.stream().parallel().forEach(order->{
        rules.forEach(rule->{
            System.out.println(order+"-"+rule);
        });
    });
}

टेस्ट: https://ideone.com/95Cybg
उदाहरण आउटपुट:

order2-rule1
order2-rule2
order2-rule3
order1-rule1
order1-rule2
order1-rule3
order4-rule1
order4-rule2
order4-rule3
order3-rule1
order3-rule2
order3-rule3

एस का क्रम orderमिश्रित है, लेकिन ruleएस हमेशा 1-2-3 होते हैं। मुझे लगता है कि आपका आउटपुट बस युग्मों को छिपाता है (वास्तव में आपने यह नहीं दिखाया कि यह कैसे उत्पन्न होता है)।

बेशक, इसे कुछ देरी के साथ बढ़ाया जा सकता है, इसलिए एस का प्रसंस्करण orderवास्तव में ओवरलैप होगा:

public static void delay(){
    try{
        Thread.sleep(ThreadLocalRandom.current().nextInt(100,300));
    }catch(Exception ex){}
}

public static void main (String[] args) throws java.lang.Exception
{
    List<String> orders = Arrays.asList("order1", "order2", "order3", "order4");
    List<String> rules = Arrays.asList("rule1", "rule2", "rule3");
    orders.stream().parallel().forEach(order->{
        rules.forEach(rule->{
            delay();
            System.out.println(order+"-"+rule);
        });
    });
}

परीक्षण: https://ideone.com/cSFaqS
उदाहरण आउटपुट:

order3-rule1
order2-rule1
order2-rule2
order3-rule2
order3-rule3
order2-rule3
order1-rule1
order4-rule1
order1-rule2
order4-rule2
order4-rule3
order1-rule3

यह कुछ ऐसा हो सकता है जिसे आपने देखा है, सिर्फ orderxभाग के बिना । साथ orderदृश्यमान है यह पता लगाया जा सकता है कि ruleरों 1-2-3 आते हैं, प्रतिorder । साथ ही, आपकी उदाहरण सूची में order1दो बार निहित है जो यह देखने में मदद नहीं करता है कि क्या हो रहा था।


जवाब के लिए धन्यवाद। उपरोक्त आउटपुट आदेशों की कम संख्या के लिए सही हो सकता है। लेकिन अगर आप ऑर्डर बढ़ाते हैं, तो आपको एक अलग आउटपुट मिलेगा। पूर्व के लिए।
मयंक बिश्ट

आदेशों का क्रम कुछ भी हो सकता है, लेकिन नियमों का क्रम नहीं बदलना चाहिए। इसके अलावा एक विशेष आदेश के लिए नियम एक समूह में आना चाहिए। पूर्व के लिए। (order1- नियम 1 order1-rule2 order1-rule3) और नहीं (order1-rule1 order2-rule1 order1-rule2 order1-rule3))।
बिष्ट मयंक

@mayankbisht मुझे लगता है कि ये प्रतिबंध केवल समानांतर प्रसंस्करण की अनुमति नहीं देते हैं। अद्यतन उत्तर देखें (मैंने शुरुआत में नया भाग लिखा था)।
तेवमादर

हाँ, मैं समझता हूँ कि, और यही कारण है कि मैंने इस सवाल को यहाँ पोस्ट किया है। मुझे लगा कि शायद ऐसा करने का एक और तरीका है, या शायद हम अहंकार को बदल सकते हैं
mayank bisht

@mayankbisht आप वर्णन orderकर सकते हैं कि ओवरलैप क्यों नहीं हो सकता (क्या वे ruleशायद स्टेटफुल हैं, और सीमित संख्या में प्रतियों में मौजूद हैं, शायद केवल एक ही?)। लेकिन आम तौर पर समानांतर चलने वाली चीजों के बिना कोई समानता नहीं होती है, यही समानता की पूरी बात है।
तेवमदर

0

यदि आप तृतीय-पक्ष लाइब्रेरी का प्रयास करने में कोई आपत्ति नहीं करते हैं। यहाँ मेरा पुस्तकालय के साथ नमूना है: अबैकस-उपयोग

StreamEx.of(orders).parallelStream().forEach(order -> {}}

और आप थ्रेड नंबर भी निर्दिष्ट कर सकते हैं:

StreamEx.of(orders).parallelStream(maxThreadNum).forEach(order -> {}}

का आदेश ruleरखा जाएगा।

वैसे, चूंकि यह समानांतर धारा में है, कोड का टुकड़ा ...finalList.add(...सबसे अधिक संभावना नहीं है। मुझे लगता है कि सूची में परिणाम एकत्र करना बेहतर है:

StreamEx.of(orders).parallelStream().map/flatMap(order -> {...}}.toList()

यदि आप orderबाद में किसी कारण से आदेश रखना चाहते हैं तो भी यह उल्लेखनीय है :

StreamEx.of(orders).indexed().parallelStream()
      .map/flatMap(order -> {...}}.sortedBy(...index).toList()
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.