बीच क्या अंतर है Futureऔर Promise?
वे दोनों भविष्य के परिणामों के लिए एक प्लेसहोल्डर की तरह काम करते हैं, लेकिन मुख्य अंतर कहां है?
बीच क्या अंतर है Futureऔर Promise?
वे दोनों भविष्य के परिणामों के लिए एक प्लेसहोल्डर की तरह काम करते हैं, लेकिन मुख्य अंतर कहां है?
जवाबों:
इस चर्चा के अनुसार , Promiseअंत CompletableFutureमें जावा 8 में शामिल करने के लिए बुलाया गया है , और इसका जावाडॉक बताते हैं:
एक भविष्य जिसे स्पष्ट रूप से पूरा किया जा सकता है (इसके मूल्य और स्थिति को निर्धारित करना), और एक पूर्णता के रूप में उपयोग किया जा सकता है, आश्रित कार्यों और कार्यों का समर्थन करता है जो इसके पूरा होने पर ट्रिगर होते हैं।
एक उदाहरण सूची में भी दिया गया है:
f.then((s -> aStringFunction(s)).thenAsync(s -> ...);
ध्यान दें कि अंतिम API थोड़ा अलग है लेकिन समान एसिंक्रोनस निष्पादन की अनुमति देता है:
CompletableFuture<String> f = ...;
f.thenApply(this::modifyString).thenAccept(System.out::println);
(मैं अब तक के जवाबों से पूरी तरह खुश नहीं हूं, इसलिए यहां मेरा प्रयास है ...)
मुझे लगता है कि केविन राइट की टिप्पणी ( "आप एक वादा कर सकते हैं और इसे बनाए रखने के लिए आप पर निर्भर है। जब कोई व्यक्ति आपसे कोई वादा करता है तो आपको यह देखने के लिए इंतजार करना होगा कि क्या वे इसे भविष्य में सम्मानित करते हैं" ) इसे अच्छी तरह से संक्षेप में प्रस्तुत करता है, लेकिन कुछ स्पष्टीकरण उपयोगी हो सकता है।
वायदा और वादे काफी समान अवधारणाएं हैं, अंतर यह है कि भविष्य एक परिणाम के लिए केवल-पढ़ने वाला कंटेनर है जो अभी तक मौजूद नहीं है, जबकि एक वादा लिखा जा सकता है (आमतौर पर केवल एक बार)। जावा 8 CompletableFuture और अमरूद SettableFuture , वादे के बारे में सोचा जा सकता है क्योंकि उनके मूल्य ( "पूरा") सेट किया जा सकता, लेकिन वे भी भविष्य इंटरफ़ेस को लागू है, इसलिए वहाँ ग्राहक के लिए कोई अंतर नहीं है।
भविष्य का परिणाम "किसी और के द्वारा" सेट किया जाएगा - एक अतुल्यकालिक गणना के परिणाम से। ध्यान दें कि FutureTask - एक क्लासिक भविष्य - को एक कॉल करने योग्य या रननेबल के साथ आरंभीकृत किया जाना चाहिए, कोई भी तर्क-वितर्क नहीं है, और Future और FutureTask दोनों ही बाहर से पढ़े जाते हैं (FutureTask के सेट के तरीके सुरक्षित हैं)। मूल्य को अंदर से गणना के परिणाम पर सेट किया जाएगा।
दूसरी ओर, किसी भी वादे का परिणाम "आप" (या वास्तव में किसी के द्वारा) सेट किया जा सकता है क्योंकि इसमें एक सार्वजनिक सेट विधि है। दोनों पूर्णरूपेण सिलाई और SettableFuture किसी भी काम के बिना बनाया जा सकता है, और उनके मूल्य किसी भी समय सेट किया जा सकता है। आप ग्राहक कोड को एक वादा भेजते हैं, और बाद में इसे अपनी इच्छानुसार पूरा करते हैं।
ध्यान दें कि कंप्लीटटेबल सीवन एक "शुद्ध" वादा नहीं है, इसे फ्यूचरटैस्क की तरह एक कार्य के साथ शुरू किया जा सकता है, और इसकी सबसे उपयोगी विशेषता प्रसंस्करण चरणों की असंबंधित चेनिंग है।
यह भी ध्यान दें कि एक वादा भविष्य का उपप्रकार नहीं होता है और इसे एक ही वस्तु होने की आवश्यकता नहीं होती है। स्काला में एक भविष्य की वस्तु एक अतुल्यकालिक गणना या एक अलग वादा वस्तु द्वारा बनाई गई है । C ++ में स्थिति समान है: वादा वस्तु का उपयोग निर्माता और भविष्य की वस्तु उपभोक्ता द्वारा किया जाता है। इस पृथक्करण का लाभ यह है कि ग्राहक भविष्य का मूल्य निर्धारित नहीं कर सकता है।
स्प्रिंग और EJB 3.1 दोनों में एक AsyncResult क्लास है, जो स्काला / C ++ वादों के समान है। AsyncResult फ्यूचर को कार्यान्वित करता है, लेकिन यह वास्तविक भविष्य नहीं है: स्प्रिंग / EJB में एसिंक्रोनस तरीके कुछ पृष्ठभूमि जादू के माध्यम से एक अलग, केवल-पढ़ने के लिए फ्यूचर ऑब्जेक्ट लौटाते हैं, और परिणाम का उपयोग करने के लिए क्लाइंट द्वारा इस दूसरे "वास्तविक" भविष्य का उपयोग किया जा सकता है।
मुझे पता है कि पहले से ही एक स्वीकृत उत्तर है, लेकिन फिर भी मैं अपने दो सेंट जोड़ना चाहूंगा:
TLDR: भविष्य और वादा एक अतुल्यकालिक ऑपरेशन के दो पक्ष हैं: उपभोक्ता / कॉलर बनाम निर्माता / कार्यान्वयनकर्ता ।
एक अतुल्यकालिक एपीआई विधि के कॉलर के रूप में , आपको Futureगणना के परिणाम के रूप में एक हैंडल मिलेगा । आप उदाहरण get()के लिए गणना पूरी होने और परिणाम प्राप्त करने के लिए प्रतीक्षा करने के लिए उस पर कॉल कर सकते हैं ।
अब सोचें कि यह एपीआई विधि वास्तव में कैसे लागू की गई है: कार्यान्वयनकर्ता को Futureतुरंत वापस लौटना चाहिए । गणना पूरा होते ही वे उस भविष्य को पूरा करने के लिए जिम्मेदार होते हैं (जो उन्हें पता होगा क्योंकि यह प्रेषण तर्क को लागू कर रहा है ;-))। वे ऐसा करने के लिए a Promise/ CompletableFutureका उपयोग करेंगे : निर्माण और CompletableFutureतुरंत वापस , और complete(T result)एक बार गणना करने के बाद कॉल करें ।
मैं एक उदाहरण दूंगा कि प्रॉमिस क्या है और फ्यूचर के विपरीत किसी भी समय इसका मूल्य कैसे निर्धारित किया जा सकता है, कौन सा मूल्य केवल पठनीय है।
मान लीजिए आपके पास एक माँ है और आप उससे पैसे मांगते हैं।
// Now , you trick your mom into creating you a promise of eventual
// donation, she gives you that promise object, but she is not really
// in rush to fulfill it yet:
Supplier<Integer> momsPurse = ()-> {
try {
Thread.sleep(1000);//mom is busy
} catch (InterruptedException e) {
;
}
return 100;
};
ExecutorService ex = Executors.newFixedThreadPool(10);
CompletableFuture<Integer> promise =
CompletableFuture.supplyAsync(momsPurse, ex);
// You are happy, you run to thank you your mom:
promise.thenAccept(u->System.out.println("Thank you mom for $" + u ));
// But your father interferes and generally aborts mom's plans and
// completes the promise (sets its value!) with far lesser contribution,
// as fathers do, very resolutely, while mom is slowly opening her purse
// (remember the Thread.sleep(...)) :
promise.complete(10);
उस का आउटपुट है:
Thank you mom for $10
माँ का वादा बनाया गया था, लेकिन कुछ "पूरा होने" की घटना का इंतजार कर रहा था।
CompletableFuture<Integer> promise...
आपने इस तरह का आयोजन किया, उसके वादे को स्वीकार किया और अपनी माँ को धन्यवाद देने के लिए अपनी योजनाओं की घोषणा की:
promise.thenAccept...
इस क्षण माँ ने अपना पर्स खोलना शुरू किया ... लेकिन बहुत धीमी ...
और पिता ने बहुत तेजी से हस्तक्षेप किया और अपनी माँ के बदले वादा पूरा किया:
promise.complete(10);
क्या आपने एक निष्पादक पर ध्यान दिया है जिसे मैंने स्पष्ट रूप से लिखा है?
दिलचस्प बात यह है कि, यदि आप इसके बजाय (कॉमनपूल) डिफॉल्ट इम्प्लिमेंट एक्ज़ीक्यूटर का उपयोग करते हैं और पिता घर पर नहीं हैं, लेकिन केवल माँ "उनके" धीमे पर्स "के साथ हैं, तो उनका वादा केवल पूरा होगा, अगर प्रोग्राम को मॉम की तुलना में अधिक समय तक रहने के लिए पैसे प्राप्त करने की आवश्यकता है पर्स।
डिफ़ॉल्ट निष्पादक एक "डेमॉन" की तरह काम करता है और सभी वादे पूरे होने का इंतजार नहीं करता है। मुझे इस तथ्य का अच्छा विवरण नहीं मिला है ...
निश्चित नहीं है कि यह एक उत्तर हो सकता है लेकिन जैसा कि मैंने देखा कि दूसरों ने किसी के लिए क्या कहा है, ऐसा लग सकता है कि आपको इन दोनों अवधारणाओं के लिए दो अलग-अलग अमूर्त की आवश्यकता है ताकि उनमें से एक ( Future) केवल दूसरे का केवल पढ़ने के लिए ( Promise) ... लेकिन वास्तव में इसकी जरूरत नहीं है।
उदाहरण के लिए एक नज़र डालें कि कैसे जावास्क्रिप्ट में वादों को परिभाषित किया जाता है:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
ध्यान केंद्रित करने की thenविधि का उपयोग कर की तरह है:
asyncOp1()
.then(function(op1Result){
// do something
return asyncOp2();
})
.then(function(op2Result){
// do something more
return asyncOp3();
})
.then(function(op3Result){
// do something even more
return syncOp4(op3Result);
})
...
.then(function(result){
console.log(result);
})
.catch(function(error){
console.log(error);
})
जो तुल्यकालिक की तरह दिखने के लिए अतुल्यकालिक गणना करता है:
try {
op1Result = syncOp1();
// do something
op1Result = syncOp2();
// do something more
op3Result = syncOp3();
// do something even more
syncOp4(op3Result);
...
console.log(result);
} catch(error) {
console.log(error);
}
जो बहुत अच्छा है। (नहीं के रूप में के रूप में शांत async- वेट लेकिन async- वेट सिर्फ बॉयलरप्लेट निकालता है .... फिर (फ़ंक्शन (परिणाम) {.... इससे)।
और वास्तव में उनके अमूर्त वादे निर्माता के रूप में बहुत अच्छा है
new Promise( function(resolve, reject) { /* do it */ } );
आपको दो कॉलबैक प्रदान करने की अनुमति देता है जिसका उपयोग या तो Promiseसफलतापूर्वक या किसी त्रुटि के साथ किया जा सकता है । ताकि केवल निर्माण करने वाला कोड ही Promiseइसे पूरा कर सके और पहले से निर्मित Promiseवस्तु प्राप्त करने वाले कोड में रीड-ओनली व्यू हो।
इनहेरिटेंस के साथ उपरोक्त प्राप्त किया जा सकता है यदि संकल्प और अस्वीकार संरक्षित तरीके हैं।
CompletableFutureकुछ समानता हो सकती है, Promiseलेकिन यह अभी भी एक नहीं हैPromise , क्योंकि जिस तरह से इसका उपभोग करने का इरादा है वह अलग है: Promiseकॉल करने से परिणाम का उपभोग होता है then(function), और निर्माता द्वारा कॉल के तुरंत बाद फ़ंक्शन को निर्माता के संदर्भ में निष्पादित किया जाता है।resolve । एक Futureपरिणाम को कॉल करके उपभोग किया जाता है getजिसके कारण उपभोक्ता थ्रेड इंतजार करता है जब तक कि निर्माता थ्रेड ने मान उत्पन्न नहीं किया है, तब इसे उपभोक्ता में संसाधित करता है। Futureस्वाभाविक रूप से
Promiseकेवल एक ही धागे के साथ उपयोग करना पूरी तरह से संभव है (और वास्तव में यह सटीक वातावरण है जिसे वे मूल रूप से डिजाइन किए गए थे: जावास्क्रिप्ट अनुप्रयोगों में आमतौर पर केवल एक ही धागा होता है, इसलिए आप वहां लागू नहीं कर सकते हैंFuture )। Promiseइसलिए की तुलना में बहुत अधिक हल्का और कुशल है Future, लेकिन Futureऐसी परिस्थितियों में सहायक हो सकता है जो अधिक जटिल हैं और थ्रेड्स के बीच सहयोग की आवश्यकता होती है जो आसानी से Promiseएस का उपयोग करके व्यवस्थित नहीं किया जा सकता है । संक्षेप में कहें : Promiseएक पुश मॉडल है, जबकि Futureएक पुल मॉडल है (cf Iterable vs Observable)
XMLHttpRequest)। मैं दक्षता के दावे पर विश्वास नहीं करता, क्या आपके पास कुछ आंकड़े हैं? +++ ने कहा, बहुत अच्छी व्याख्या।
getएक अनसुलझे कॉल पर Futureजरूरी 2 थ्रेड संदर्भ स्विच शामिल होंगे, जिनकी कम से कम कुछ साल पहले हमें लगभग 50 की आवश्यकता थी ।
क्लाइंट कोड के लिए, एक परिणाम उपलब्ध होने पर कॉलबैक देखने या संलग्न करने के लिए वादा करता है, जबकि भविष्य परिणाम के लिए इंतजार करना और फिर जारी रखना है। सैद्धांतिक रूप से कुछ भी जो वायदा के साथ करना संभव है, जो वादों के साथ किया जा सकता है, लेकिन शैली के अंतर के कारण, विभिन्न भाषाओं में वादों के लिए परिणामी एपीआई आसान हो जाता है।
फ्यूचर इंटरफेस में कोई सेट विधि नहीं है, केवल विधि प्राप्त करें, इसलिए यह केवल पढ़ने के लिए है। कंप्लीटटेबल सीमेंट के बारे में, यह लेख शायद सहायक हो। completablefuture
Promiseइसे बनाकर रख सकते हैं। जब कोई दूसरा आपको एक वादा करता है तो आपको यह देखने के लिए इंतजार करना होगा कि क्या वे इसे सम्मानित करते हैंFuture