2017-03-09 8 views
5

मेरे पास कुछ रिपोजिटरी क्लास पर एक विधि है जो CompletableFuture देता है। कोड जो इन वायदा को पूरा करता है, एक थर्ड पार्टी लाइब्रेरी का उपयोग करता है जो ब्लॉक करता है। मेरा इरादा अलग-अलग Executor है जो इस भंडार वर्ग को इन अवरुद्ध कॉल करने के लिए उपयोग करेगा।जावा CompletableFutures लिखते समय कौन सा निष्पादक उपयोग किया जाता है?

यहाँ एक उदाहरण है:

public class PersonRepository { 
    private Executor executor = ... 
    public CompletableFuture<Void> create(Person person) {...} 
    public CompletableFuture<Boolean> delete(Person person) {...} 
} 

अपने आवेदन परिणामों के साथ इन वायदा कुछ अन्य बातों लिखें और क्या करेंगे के बाकी। जब इन अन्य कार्यों को thenAccept, thenCompose, whenComplete, आदि के लिए आपूर्ति की जाती है, तो मैं नहीं चाहता कि वे भंडार के लिए Executor पर चलें।

एक और उदाहरण:

public CompletableFuture<?> replacePerson(Person person) { 
    final PersonRepository repo = getPersonRepository(); 
    return repo.delete(person) 
     .thenAccept(existed -> { 
      if (existed) System.out.println("Person deleted")); 
      else System.out.println("Person did not exist")); 
     }) 
     .thenCompose(unused -> { 
      System.out.println("Creating person"); 
      return repo.create(person); 
     }) 
     .whenComplete((unused, ex) -> { 
      if (ex != null) System.out.println("Creating person"); 
      repo.close(); 
     }); 
} 

JavaDoc कहता है:

क्रिया गैर async तरीकों में से निर्भर पूर्ण करने के लिए आपूर्ति की, या किसी अन्य द्वारा धागा है कि मौजूदा CompletableFuture पूरा करता है के द्वारा किया जा सकता है एक समापन विधि के कॉलर।

साइड प्रश्न: क्यों वहाँ एक या यहाँ है? किस मामले में एक पूर्णता विधि का एक और कॉलर है जो वर्तमान भविष्य को पूरा नहीं करता है?

मुख्य प्रश्न: मैं सभी println, एक अलग Executor भंडार द्वारा इस्तेमाल किया एक से द्वारा निष्पादित की जाने जो तरीकों मैं async बनाने के लिए और मैन्युअल निष्पादक प्रदान करने की आवश्यकता है चाहते हैं?

स्पष्ट रूप से thenAccept को thenAcceptAsync में बदला जाना आवश्यक है, लेकिन मुझे उस बिंदु के बारे में निश्चित नहीं है।

वैकल्पिक प्रश्न: कौन सा धागा thenCompose से लौटा हुआ भविष्य पूरा करता है?

मेरा अनुमान है कि यह थ्रेड होगा जो भविष्य में फ़ंक्शन तर्क से लौटाए गए भविष्य को पूरा करेगा। दूसरे शब्दों में मुझे whenComplete से whenCompleteAsync को भी बदलने की आवश्यकता होगी।

शायद मैं जटिल चीजों से अधिक हूं लेकिन ऐसा लगता है कि यह काफी मुश्किल हो सकता है। मुझे बहुत ध्यान देना होगा कि ये सभी वायदा कहाँ से आते हैं। एक डिजाइन बिंदु से भी, यदि मैं भविष्य लौटाता हूं, तो मैं कॉलर्स को अपने निष्पादक का उपयोग करने से कैसे रोकूं? ऐसा लगता है जैसे यह encapsulation तोड़ता है। मुझे पता है कि स्कैला में सभी परिवर्तन कार्य एक अंतर्निहित ExecutionContext लेते हैं जो इन सभी समस्याओं को हल करने लगता है।

+2

उस लेख को पढ़ें - http://www.nurkiewicz.com/2015/11/which-thread-executes.html। यह थ्रेड पर प्रकाश को छाया करने में मदद करता है – rvit34

उत्तर

4

साइड प्रश्न: यदि आपने इंटरमीडिएट CompletionStage को एक चर के लिए असाइन किया है और उस पर एक विधि कॉल किया है, तो यह उसी धागे पर निष्पादित हो जाएगा।

मुख्य प्रश्न: केवल पहला, इसलिए thenAccept से thenAcceptAsync में बदलें - सभी निम्नलिखित स्वीकृति के लिए उपयोग किए गए थ्रेड पर अपने चरणों को निष्पादित करेंगे।

वैकल्पिक प्रश्न: thenCompose से भविष्य को पूरा करने वाला धागा वही है जो रचना के लिए उपयोग किया गया था।

आपको पूर्ण चरणों के चरणों के बारे में सोचना चाहिए, जो कि उसी थ्रेड पर तेजी से उत्तराधिकार में निष्पादित होते हैं (केवल क्रम में कार्यों को लागू करके), जब तक कि आप विशेष रूप से एसिंक का उपयोग करके किसी भिन्न थ्रेड पर चरण निष्पादित नहीं करना चाहते हैं। तब सभी नए कदम उस नए धागे पर किए जाते हैं।

अपने मौजूदा सेटअप में चरणों का इस तरह क्रियान्वित किया जाएगा:

Thread-1: delete, accept, compose, complete 
पहले स्वीकार async के साथ

, यह हो जाता है:

Thread-1: delete 
Thread-2: accept, compose, complete 

अपने आखिरी सवाल का सवाल है, के बारे में एक ही धागे से किया जा रहा यदि आप अतिरिक्त चरणों को जोड़ते हैं तो आपके कॉलर्स द्वारा उपयोग किया जाता है - मुझे नहीं लगता कि CompletableFuture वापस नहीं लौटने से, आप एक सामान्य Future लौटने से कुछ भी कर सकते हैं।

+0

साइड प्रश्न का आपका जवाब मुझे समझ में नहीं आता है। असाइनमेंट में कोई फर्क नहीं पड़ता है। आपके उत्तरों का भी विरोधाभास है कि @ जो-सी ने कहा और ऊपर टिप्पणी में लेख। अगर मैंने समझ लिया है कि उन्होंने क्या कहा है तो कुछ भी आवश्यक थ्रेड (एसिंक के बिना) पर निष्पादित नहीं होगा जब तक वे संरचना के दौरान या तो पूर्ण या सभी अपूर्ण नहीं होते। यदि रचना के दौरान किसी बिंदु पर मध्यवर्ती भविष्य पूरा हो जाता है तो अगली संरचना वर्तमान धागे में चली जाएगी। – Steiny

+0

हाँ, मैंने कहा कि अस्पष्ट, यह और अधिक है कि यदि आप काफी लंबे समय तक एक मंच रखते हैं, और यह पहले से ही पूरा हो गया है, तो उस पर अधिक रचनाएं कॉलर थ्रेड पर होंगी। ताकि "या" दस्तावेज़ों में मूल रूप से उस मामले के लिए है जहां चरण पहले ही पूरा हो चुके हैं। – john16384

+0

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

4

बस इसके साथ खेलने के दौरान मेरे अनुभवजन्य अवलोकनों से, थ्रेड जो इन गैर-एसिंक विधियों को निष्पादित करता है, इस पर निर्भर करेगा कि पहले होता है, thenCompose स्वयं या Future के पीछे का कार्य।

यदि thenCompose पहले पूरा करता है (जो, आपके मामले में, लगभग निश्चित है), तो विधि Future कार्य निष्पादित करने वाले उसी थ्रेड पर चल जाएगी।

यदि आपके Future के पीछे का कार्य पहले पूरा हो जाता है, तो विधि तुरंत कॉलिंग थ्रेड पर चलती है (यानी कोई निष्पादक नहीं)।

+0

बिल्कुल हां हां। मैंने यह नहीं सोचा था कि वर्तमान भविष्य ने उन्हें तैयार करने से पहले अन्य भविष्य वास्तव में पूरा कर लिया है (हालांकि जैसा कि आपने बताया है कि यह मेरे मामले में काफी संभावना नहीं है)। मैं अभी भी आंतरिक भविष्य के बारे में सोचता हूं, हालांकि, उसी तर्क को लागू करने के लिए ऐसा लगता है कि परिणामस्वरूप कोई भी इसके लिए निष्पादक द्वारा पूरा किया जा सकता है। मुझे उस पर थोड़ा और प्रयोग करना पड़ सकता है – Steiny

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