Bir Gelecek ve Bir Söz arasındaki fark nedir?


274

Arasındaki fark nedir Futureve Promise?
Her ikisi de gelecekteki sonuçlar için bir yer tutucu gibi davranıyor, ancak temel fark nerede?


99
Bir yapabilirsiniz Promiseve onu tutmak size kalmış. Birisi size bir söz verdiğinde, onurlandırıp Future
Kevin Wright

1
wikipedia Gelecek ve vaatler
wener

30
Şimdiye kadar okuduğum en az yardımcı Wikipedia makalelerinden biri
Fulluphigh

Yanıtlar:


146

Göre bu tartışmada , Promisenihayet adı olmuştur CompletableFutureJava 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);

78
Bu senin hatan Assylias değil, ama javadoc özü iyi bir teknoloji yazarı tarafından ciddi bir çalışma gerektiriyor. Beşinci okuduğumda, söylemeye çalıştığı şeyi takdir etmeye başlayabilirim ... ve buna zaten mevcut olan gelecekler ve vaatler anlayışıyla geliyorum!
Pancar-Pancar

2
@ Beetroot-Beetroot şu ana kadar olmuş gibi görünüyor.
Herman

1
@herman Teşekkürler - Bağlantıyı javadoc'un son sürümüne işaret edecek şekilde güncelledim.
assylias

7
@ Beetroot-Beetroot İstisnai yöntem için dokümanı kontrol etmelisiniz. Harika bir şiir yapar, ancak okunabilir belgelerin olağanüstü bir başarısızlığıdır.
Fulluphigh

4
Herkes merak için @Fulluphigh bahsediyor bu . Görünüşe göre Java 8'de kaldırıldı / elden geçirildi
Cedric Reichenbach

148

(Ş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.


116

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 Futurehesaplama 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/ CompletableFuturekomutunu kullanırlar: CompletableFutureDerhal yapılandırın ve geri dönün complete(T result)ve hesaplama yapıldıktan sonra arayın .


1
Bu, bir Sözün her zaman Geleceğin bir alt sınıfı olduğunu ve Geleceğin yazılabilirliğinin tür tarafından gizlendiğini mi ima ediyor?
devios1

Zımni olduğunu sanmıyorum . Uygulama açısından, genellikle böyle olacaktır (örneğin Java, Scala'da).
Rahel Lüthy

74

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 ...


8
Bunu okumak çok eğlenceli! Artık geleceği unutabileceğimi ve söz verebileceğimi sanmıyorum.
user1532146

2
Bu cevap olarak kabul edilmelidir. Tıpkı bir hikaye okumak gibi. @Vladimir
Phillen

@Vladimir
intvprep

9

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://promisesaplus.com/

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

Odak aşağıdaki thengibi 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 */ } );

Promisebaş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 Promiseonu tamamlayabilir ve önceden oluşturulmuş bir Promisenesneyi 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 .


4
+1. Bu soruya doğru cevap bu. CompletableFutureile benzerlik gösterebilir, Promiseancak 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 Futuresonucu, gettü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 . Futuredoğal olarak çok iş parçacıklı, ama ...
Periata Breatta

5
... Bir kullanmak tamamen mümkün olduğunu Promisesadece 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 Futureorada). Promisebu nedenle çok daha hafif ve etkilidir Future, ancak Futuredaha karmaşık olan ve Promises kullanılarak kolayca düzenlenemeyen iplikler arasında işbirliği gerektiren durumlarda yardımcı olabilir . Özetlemek gerekirse: Promisebir itme Future
modeliyken

@PeriataBreatta Tek iş parçacıklı bir ortamda bile, vaadi yerine getiren bir şey olmalıdır (bu genellikle farklı bir iş parçacığı gibi çalışır, örneğin bir XMLHttpRequest). Verimlilik iddiasına inanmıyorum, bazı rakamlarınız var mı? +++ Bunu söyledi, çok güzel bir açıklama.
maaartinus

1
@maaartinus - evet, bir şey vaadi yerine getirmelidir, ancak dış durumdaki değişiklikler için anket yapan ve biten eylemlerle ilgili hangi vaatleri çözen bir üst düzey döngü kullanarak yapılabilir (ve aslında birçok durumda). Verimlilik açısından, sözler için kesin bir rakamım yok, ancak getçözülmemiş olarak çağırmanın Futuremutlaka en az birkaç yıl önce yaklaşık 50 bize ihtiyaç duyacağı 2 iplik bağlamı anahtarını içereceğini unutmayın .
Periata Breatta

@PeriataBreatta Aslında yorumunuz kabul edilen çözüm olmalıdır. Seninki gibi bir açıklama (çekme / itme, tek / çoklu iplik) arıyordum.
Thomas Jacob

5

İ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.


2

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.