2016-03-28 8 views
14

मैं सिर्फ जावा 8. के ​​कुछ संगामिति सुविधाओं की खोज शुरू कर दिया है एक बात मुझे उलझन में थोड़ा इन दोनों स्थिर तरीकों है:CompletableFuture supplyAsync

CompletableFuture<Void> runAsync(Runnable runnable) 
CompletableFuture<U> supplyAsync(Supplier<U> supplier) 

किसी को भी पता है क्यों वे इंटरफ़ेस प्रदायक उपयोग करने के लिए चुनते हैं? कॉलबल का उपयोग करना अधिक स्वाभाविक नहीं है, जो रननेबल का समानता है जो मूल्य देता है? क्या ऐसा इसलिए है क्योंकि प्रदायक एक अपवाद नहीं फेंकता है जिसे संभाला नहीं जा सकता है?

+0

क्योंकि वे सिर्फ सी #, जो सामान्य रूप से नामित किया है 'कार्रवाई <>' और 'से अलग होना ही था Func <> 'इंटरफेस जो एक ही काम करते हैं लेकिन प्रोग्रामर को भ्रमित किए बिना। और इसलिए उन्होंने समान हस्ताक्षरों के साथ विधियों के लिए कार्यात्मक इंटरफेस को बढ़ाया लेकिन अलग-अलग नाम। उन्होंने शायद सोचा था कि यह प्रोग्रामर को उनके साथ काम करने के लिए एक मानसिक मॉडल देकर मदद करेगा, लेकिन ऐसा नहीं है: यह सिर्फ मामूली पिटा है। – davidbak

उत्तर

7

लघु जवाब

नहीं, यह CompletableFuture.supplyAsync में Callable बजाय Supplier उपयोग करने के लिए और अधिक प्राकृतिक नहीं है। तर्क लगभग पूरी तरह से अर्थशास्त्र के बारे में है, इसलिए यह ठीक है अगर आप अभी भी असुविधाजनक महसूस करते हैं।

लांग जवाब

Callable और Supplier कार्यात्मक इंटरफेस/सैम प्रकार के समारोह में व्यावहारिक रूप से बराबर हैं (यमक क्षमा), लेकिन उनकी उत्पत्ति और इच्छित उपयोग भिन्न होते हैं।

Callablejava.util.concurrent पैकेज के हिस्से के रूप में बनाया गया था। यह पैकेज जावा 8 में लैम्ब्डा अभिव्यक्तियों के विशाल परिवर्तन से पहले आया था और मूल रूप से कई प्रकार के औजारों पर केंद्रित था, जो आपको समेकित कोड लिखने में मदद करता था, बिना मल्टीथ्रेडिंग के क्लासिक मॉडल से ज्यादा विचलित किए।

Callable का मुख्य उद्देश्य एक क्रिया को सार करना था जिसे एक अलग थ्रेड में निष्पादित किया जा सकता था और परिणामस्वरूप इसका परिणाम मिलता है। Callable के जावाडोक से:

Callable इंटरफेस, Runnable के समान है कि दोनों वर्गों जिसका उदाहरणों संभावित एक और धागा द्वारा क्रियान्वित कर रहे के लिए तैयार कर रहे हैं में।

Supplierjava.util.function पैकेज के भाग के रूप में बनाया गया था। वह पैकेज जावा 8 में उपर्युक्त परिवर्तनों का एक अभिन्न अंग के रूप में आया था। यह सामान्य कार्यात्मक प्रकार प्रदान करता है जिसे लैम्ब्डा अभिव्यक्तियों और विधि संदर्भों द्वारा लक्षित किया जा सकता है।

ऐसा एक प्रकार पैरामीटर के बिना एक फ़ंक्शन है जो परिणाम देता है (यानी कोई ऐसा फ़ंक्शन जो कुछ प्रकार या Supplier फ़ंक्शन प्रदान करता है)।

तो Supplier और Callable क्यों नहीं?

CompletableFuture बजाय स्पष्ट रूप से इसे भीतर संगामिति से निपटने में, java.util.concurrent पैकेज है कि जावा 8 में ऊपर उल्लिखित परिवर्तन से प्रेरित थे और है कि डेवलपर एक कार्यात्मक, परोक्ष में चलाने योग्य ढंग से अपने कोड के निर्माण के लिए अनुमति देने के लिए जोड़ का हिस्सा है।

इसकी supplyAsync विधि को एक विशिष्ट प्रकार का परिणाम प्रदान करने और इस परिणाम में इसके लिए अधिक रुचि रखने का एक तरीका चाहिए, न कि इस परिणाम तक पहुंचने के लिए किए गए कदम में। यह भी असाधारण पूरा होने की परवाह नहीं करता है (भी देखें ... पैराग्राफ के बारे में क्या)।

फिर भी, यदि Runnable नहीं मापदंडों के लिए प्रयोग किया जाता है, कोई परिणाम कार्यात्मक इंटरफ़ेस, Callable नहीं कोई पैरामीटर के लिए, प्रयोग किया जाना चाहिए एकल परिणाम कार्यात्मक इंटरफ़ेस?

आवश्यक नहीं है।

एक ऐसे फ़ंक्शन के लिए एक अमूर्त जिसमें पैरामीटर नहीं है और परिणाम नहीं लौटाता है (और इसलिए बाहरी संदर्भ पर साइड इफेक्ट्स के माध्यम से पूरी तरह से संचालित होता है) java.util.function में शामिल नहीं किया गया था। इसका मतलब यह है कि (कुछ हद तक परेशान) Runnable का उपयोग किया जाता है जहां भी एक कार्यात्मक इंटरफ़ेस की आवश्यकता होती है।

चेक Exception के बारे में क्या है जिसे Callable.call() द्वारा फेंक दिया जा सकता है?

यह Callable और Supplier के बीच इच्छित अर्थपूर्ण अंतर का एक छोटा सा संकेत है।

Callable एक ऐसी क्रिया है जिसे किसी अन्य धागे में निष्पादित किया जा सकता है, और इससे आप इसके निष्पादन के परिणामस्वरूप इसके दुष्प्रभावों का निरीक्षण कर सकते हैं। यदि सब कुछ ठीक हो जाता है, तो आप एक विशिष्ट प्रकार का परिणाम प्राप्त करते हैं, लेकिन कुछ क्रियाओं को निष्पादित करते समय असाधारण परिस्थितियां उत्पन्न हो सकती हैं (विशेष रूप से बहुप्रचारित संदर्भ में), आप ऐसी असाधारण स्थितियों को परिभाषित और संभाल भी सकते हैं।

दूसरी ओर Supplier एक ऐसा फ़ंक्शन है जिस पर आप किसी प्रकार की वस्तुओं की आपूर्ति के लिए भरोसा करते हैं। असाधारण स्थितियों को Supplier के प्रत्यक्ष उपभोक्ता के रूप में अपनी ज़िम्मेदारी नहीं जरूरी है।

  1. ... कार्यात्मक इंटरफेस अक्सर, बनाने या डेटा परिवर्तनशील, और हैंडलिंग Exception रों एक अलग मंच हो सकता है के लिए एक बहुमंज़िला प्रक्रिया में एक विशिष्ट चरण परिभाषित करने के लिए उपयोग किया जाता है के मामले में आप परवाह: यह इसलिए है क्योंकि है
  2. ... स्पष्ट रूप से निपटने Exception रों काफी कार्यात्मक इंटरफेस, लैम्ब्डा अभिव्यक्ति और विधि की अर्थपूर्ण शक्तियों को कम कर देता का संदर्भ
+0

मुझे लगता है कि आपके तर्क कि मुख्य अंतर अर्थात् पक्ष पर है, व्यावहारिक पक्ष सही नहीं है। _CallAsync_ नामक विधि का उपयोग करके अर्थात् कुछ भी नहीं दर्शाता है कि यह परिणाम देगा। –

+0

आईएमओ एक ही कार्यक्षमता_ के लिए अलग-अलग तरीकों के साथ अलग-अलग कार्यात्मक इंटरफेस रखने का पूरा विचार (उदा।, 'कॉल() 'बनाम' प्राप्त करें() ') बीमार था और बहुत सारी परेशानियों का कारण बनता था। विशेष रूप से दो हैं: यह याद रखने की कोशिश कर रहा है कि आपको कॉल करने के लिए आवश्यक डर्न विधि क्या है और फिर आसानी से एक सप्लायर भेजने में सक्षम नहीं है जिसे आपको कॉल करने योग्य आदि की आवश्यकता है। इत्यादि। इच्छित "अर्थशास्त्र" आप सभी का वर्णन कर रहे हैं शब्दों में और कुछ भी करने के लिए कुछ भी नहीं है जो संकलक लागू करेगा और जावा दस्तावेज़ों में वर्णित या वर्णित नहीं है। सी # यह बेहतर किया। – davidbak

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