Arasındaki fark nedir Future
ve Promise
?
Her ikisi de gelecekteki sonuçlar için bir yer tutucu gibi davranıyor, ancak temel fark nerede?
Arasındaki fark nedir Future
ve Promise
?
Her ikisi de gelecekteki sonuçlar için bir yer tutucu gibi davranıyor, ancak temel fark nerede?
Yanıtlar:
Göre bu tartışmada , Promise
nihayet adı olmuştur CompletableFuture
Java 8 eklenmek üzere, ve onun javadoc açıklıyor:
Açıkça tamamlanabilen (değerini ve durumunu belirleyen) ve tamamlanmasının ardından tetiklenen bağımlı işlevleri ve eylemleri destekleyen bir CompletionStage olarak kullanılabilen bir Gelecek.
Listede de bir örnek verilmiştir:
f.then((s -> aStringFunction(s)).thenAsync(s -> ...);
Nihai API'nın biraz farklı olduğunu, ancak benzer asenkron yürütmeye izin verdiğini unutmayın:
CompletableFuture<String> f = ...;
f.thenApply(this::modifyString).thenAccept(System.out::println);
(Şimdiye kadar cevaplardan tamamen memnun değilim, işte benim girişimim ...)
Sanırım Kevin Wright'ın ( "Bir Söz verebilirsin ve bunu saklaman sana kalmış. Başka biri sana bir söz verdiğinde, Gelecekte onurlandırıp görmediklerini görmek için beklemelisin" ) bunu oldukça iyi özetliyor, ama bazıları açıklama yararlı olabilir.
Gelecekler ve vaatler oldukça benzer kavramlardır, fark, bir geleceğin henüz var olmayan bir sonuç için salt okunur bir kapsayıcı olması, ancak bir sözün yazılabilmesi (normalde sadece bir kez) olmasıdır. Java 8 CompletableFuture ve Guava SettableFuture , vaatler olarak düşünülebilir, çünkü değerleri ayarlanabilir ("tamamlandı"), ancak aynı zamanda Gelecek arayüzünü de uygularlar, bu nedenle müşteri için fark yoktur.
Geleceğin sonucu, "başkası" tarafından - eşzamansız bir hesaplama sonucu - belirlenecektir. Nasıl Not FutureTask klasik gelecek - - gerekir bir çağrılabilir veya Runnable ile başlatılır, hayır hayır-argüman yapıcısı vardır ve Gelecek ve FutureTask hem salt okunur dışarıdan (FutureTask kümesi yöntemleri korunur) vardır. Değer, içeriden hesaplamanın sonucuna ayarlanır.
Öte yandan, bir vaatin sonucu herhangi bir zamanda "siz" (veya aslında herhangi bir kişi tarafından) herhangi bir zamanda ayarlanabilir. Hem CompletableFuture hem de SettableFuture herhangi bir görev olmadan oluşturulabilir ve değerleri her zaman ayarlanabilir. Müşteri koduna bir söz gönderir ve daha sonra istediğiniz gibi yerine getirirsiniz.
CompletableFuture'un "saf" bir söz olmadığını, tıpkı FutureTask gibi bir görevle başlatılabileceğini ve en kullanışlı özelliğinin, işlem adımlarının ilişkisiz zincirlenmesidir.
Ayrıca bir sözün geleceğin bir alt türü olması gerekmediğini ve aynı nesne olması gerekmediğini unutmayın. Scala'da bir Gelecek nesnesi, eşzamansız bir hesaplama veya farklı bir Promise nesnesi tarafından oluşturulur . C ++ 'da durum benzerdir: vaat nesnesi üretici tarafından kullanılır ve gelecekteki nesne tüketici tarafından kullanılır. Bu ayrımın avantajı, müşterinin geleceğin değerini ayarlayamamasıdır.
Hem Spring hem de EJB 3.1 , Scala / C ++ vaatlerine benzer bir AsyncResult sınıfına sahiptir. AsyncResult Geleceği uygular, ancak bu gerçek gelecek değildir: İlkbahar / EJB'deki eşzamansız yöntemler, bir arka plan sihri aracılığıyla farklı, salt okunur bir Gelecek nesnesi döndürür ve bu ikinci "gerçek" gelecek, sonuca erişmek için istemci tarafından kullanılabilir.
Zaten kabul edilmiş bir cevap olduğunu biliyorum, ancak yine de iki sentimi eklemek istiyorum:
TLDR: Gelecek ve Vaat, eşzamansız bir işlemin iki yüzüdür: tüketici / arayan ile üretici / uygulayıcı .
Bir As arayan bir zaman uyumsuz API yöntemi, bir alacak Future
hesaplama sonucunun bir tutamak olarak. Örneğin get()
, hesaplamanın sonucu tamamlamasını ve almasını beklemek için bu numarayı arayabilirsiniz .
Şimdi bu API yönteminin gerçekte nasıl uygulandığını düşünün: UygulayıcıFuture
hemen geri dönmelidir . Hesaplama yapılır yapılmaz bu geleceği tamamlamakla yükümlüdürler (sevk mantığını uyguladığı için bileceklerdir ;-)). Bunu yapmak için a Promise
/ CompletableFuture
komutunu kullanırlar: CompletableFuture
Derhal yapılandırın ve geri dönün complete(T result)
ve hesaplama yapıldıktan sonra arayın .
Promise'ın ne olduğuna ve değerinin herhangi bir zamanda, Geleceğin aksine, sadece okunabilir olana nasıl ayarlanabileceğine bir örnek vereceğim.
Diyelim ki bir annen var ve ondan para istiyorsun.
// 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);
Bunun çıktısı:
Thank you mom for $10
Annemin vaadi yaratıldı, ancak bir "tamamlama" etkinliği bekledi.
CompletableFuture<Integer> promise...
Böyle bir etkinlik yarattınız, sözünü kabul ettiniz ve annenize teşekkür etme planlarınızı duyurdunuz:
promise.thenAccept...
Şu anda annem çantasını açmaya başladı ... ama çok yavaş ...
ve babam çok daha hızlı müdahale etti ve annen yerine sözünü tamamladı:
promise.complete(10);
Açıkça yazdığım bir yöneticiyi fark ettiniz mi?
İlginç bir şekilde, bunun yerine varsayılan bir örtük yürütücü kullanırsanız (commonPool) ve baba evde değil, sadece "yavaş cüzdanı" ile anne, o zaman sözünü yerine getirecek, eğer program anneden daha uzun yaşıyorsa çanta.
Varsayılan yürütücü bir tür "arka plan programı" gibi davranır ve tüm vaatlerin yerine getirilmesini beklemez. Bu gerçeğin iyi bir tanımını bulamadım ...
Bunun bir cevap olup olmayacağından emin değilim ama başkalarının birileri için söylediklerini gördüğümde, bu kavramların her ikisi için iki ayrı soyutlamaya ihtiyacınız var gibi görünebilir, böylece bunlardan biri ( Future
) diğerinin salt okunur bir görünümüdür ( Promise
) ... ama aslında buna gerek yok.
Örneğin, vaatlerin javascript'te nasıl tanımlandığına bir göz atın:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Odak aşağıdaki then
gibi bir yöntem kullanılarak oluşturulabilirlik üzerinedir :
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);
})
bu senkronize gibi görünmek için asenkron hesaplama yapar:
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);
}
ki bu oldukça havalı. ( Async-await kadar serin değil ama async-await sadece kazan plakasını kaldırır .... sonra (function (sonuç) {.... ondan).
Ve aslında soyutlamaları vaat kurucu olarak oldukça iyi
new Promise( function(resolve, reject) { /* do it */ } );
Promise
başarılı bir şekilde veya bir hatayla tamamlamak için kullanılabilecek iki geri arama vermenizi sağlar . Böylece yalnızca yapıyı oluşturan kod Promise
onu tamamlayabilir ve önceden oluşturulmuş bir Promise
nesneyi alan kod salt okunur görünüme sahip olur.
Kalıtım ile, çözme ve reddetme korumalı yöntemler ise yukarıdakilere ulaşılabilir .
CompletableFuture
ile benzerlik gösterebilir, Promise
ancak yine de a değildirPromise
, çünkü tüketilmesi amaçlanan yöntem farklıdır: a Promise
'nın sonucu çağrılarak tüketilir then(function)
ve işlev, üretici çağrısından hemen sonra üretici bağlamında yürütülür resolve
. Bir Future
sonucu, get
tüketici iş parçacığının üretici iş parçacığı değeri üretene kadar beklemesine neden olan ve daha sonra onu tüketici içinde işleyen çağrıyla tüketilir . Future
doğal olarak çok iş parçacıklı, ama ...
Promise
sadece tek iplikle (ve onlar orijinal olarak dizayn edilmis kesin bir ortam olduğunu aslında: Bunu javascript uygulamalar genellikle sadece tek bir iş parçacığı sahip olamaz uygulamak Future
orada). Promise
bu nedenle çok daha hafif ve etkilidir Future
, ancak Future
daha karmaşık olan ve Promise
s kullanılarak kolayca düzenlenemeyen iplikler arasında işbirliği gerektiren durumlarda yardımcı olabilir . Özetlemek gerekirse: Promise
bir itme Future
XMLHttpRequest
). Verimlilik iddiasına inanmıyorum, bazı rakamlarınız var mı? +++ Bunu söyledi, çok güzel bir açıklama.
get
çözülmemiş olarak çağırmanın Future
mutlaka en az birkaç yıl önce yaklaşık 50 bize ihtiyaç duyacağı 2 iplik bağlamı anahtarını içereceğini unutmayın .
İstemci kodu için Promise, bir sonuç kullanılabilir olduğunda geri aramayı gözlemlemek veya iliştirmek içindir; Gelecekteki sonuç beklemek ve sonra devam etmek içindir. Teorik olarak, geleceklerle vaatlerle yapılabilecek her şey, ancak stil farkı nedeniyle, farklı dillerde vaatler için ortaya çıkan API zincirlemeyi kolaylaştırır.
Gelecekteki arayüzde ayarlanmış bir yöntem yok, sadece yöntem olsun, bu yüzden salt okunur. CompletableFuture hakkında bu makale faydalı olabilir. completablefuture
Promise
ve onu tutmak size kalmış. Birisi size bir söz verdiğinde, onurlandırıpFuture