Wat is het verschil tussen een toekomst en een belofte?

Wat is het verschil tussen Futureen Promise?
Ze fungeren allebei als een tijdelijke aanduiding voor toekomstige resultaten, maar waar zit het grootste verschil?


Antwoord 1, autoriteit 100%

(Ik ben tot nu toe niet helemaal tevreden met de antwoorden, dus hier is mijn poging…)

Ik denk dat Kevin Wrights opmerking

Je kunt een belofte doen en het is aan jou om die te houden. Wanneer iemand anders je een belofte doet, moet je wachten om te zien of ze het in de toekomst nakomen

vat het redelijk goed samen, maar enige uitleg kan nuttig zijn.

Toekomsten en beloftenzijn vrij gelijkaardige concepten, het verschil is dat een toekomst gelezen wordt -alleen container voor een resultaat dat nog niet bestaat, terwijl een belofte kan worden geschreven (normaal gesproken slechts één keer). De Java 8 CompletableFuture en de Guava SettableFuturekan worden gezien als beloften, omdat hun waarde kan worden ingesteld (“voltooid”), maar ze implementeren ook de Future-interface, daarom is er geen verschil voor de klant.

Het resultaat van de toekomst wordt bepaald door “iemand anders” – door het resultaat van een asynchrone berekening. Merk op hoe FutureTask– een klassieker future – moetworden geïnitialiseerd met een Callable of Runnable, er is geen constructor zonder argument, en zowel Future als FutureTask zijn alleen-lezen van buitenaf (de ingestelde methoden van FutureTask zijn beveiligd). De waarde wordt van binnenuit ingesteld op het resultaat van de berekening.

Aan de andere kant kan het resultaat van een belofte door “jij” (of eigenlijk door iedereen) op elk moment worden bepaald, omdat het een openbare setter-methode heeft. Zowel CompletableFuture als SettableFuture kunnen zonder enige taak worden gemaakt en hun waarde kan op elk moment worden ingesteld. U stuurt een belofte naar de klantcode en komt deze later naar wens na.

Merk op dat CompletableFuture geen “pure” belofte is, het kan worden geïnitialiseerd met een taak zoals FutureTask, en de handigste functie is de niet-gerelateerde keten van verwerkingsstappen.

Houd er ook rekening mee dat een belofte geen subtype van de toekomst hoeft te zijn en niet hetzelfde object hoeft te zijn. In Scala wordt een Future-object gemaakt door een asynchrone berekening of door een anderPromise-object. In C++ is de situatie vergelijkbaar: het belofte-object wordt gebruikt door de producent en het toekomstige object door de consument. Het voordeel van deze scheiding is dat de klant de waarde van de toekomst niet kan bepalen.

Beide Lenteen EJB 3.1een AsyncResult-klasse hebben, die vergelijkbaar is met de Scala/C++-beloften. AsyncResult implementeert Future, maar dit is niet de echte toekomst: asynchrone methoden in Spring/EJB retourneren een ander, alleen-lezen Future-object via wat achtergrondmagie, en deze tweede “echte” toekomst kan door de client worden gebruikt om toegang te krijgen tot het resultaat.


Antwoord 2, autoriteit 88%

Volgens deze discussie, Promiseis eindelijk CompletableFuturegenoemd voor opname in Java 8, en zijn javadoclegt uit:

Een toekomst die expliciet kan worden voltooid (de waarde en status instellen) en kan worden gebruikt als een voltooiingsfase, waarbij afhankelijke functies en acties worden ondersteund die na voltooiing worden geactiveerd.

Er wordt ook een voorbeeld gegeven in de lijst:

f.then((s -> aStringFunction(s)).thenAsync(s -> ...);

Merk op dat de uiteindelijke API iets anders is, maar vergelijkbare asynchrone uitvoering mogelijk maakt:

CompletableFuture<String> f = ...;
f.thenApply(this::modifyString).thenAccept(System.out::println);

Antwoord 3, autoriteit 82%

Ik ben me ervan bewust dat er al een geaccepteerd antwoord is, maar ik wil er toch mijn twee cent aan toevoegen:

TLDR: Toekomst en Belofte zijn de twee kanten van een asynchrone operatie: consument/bellerversus producent/implementor.

Als aanroepervan een asynchrone API-methode, krijg je een Futureals handvat voor het berekeningsresultaat. Je kunt b.v. roep get()erop aan om te wachten tot de berekening is voltooid en het resultaat op te halen.

Bedenk nu hoe deze API-methode daadwerkelijk wordt geïmplementeerd: de implementormoet onmiddellijk een Futureretourneren. Ze zijn verantwoordelijk voor het voltooien van die toekomst zodra de berekening is voltooid (wat ze weten omdat het de verzendingslogica implementeert ;-)). Ze zullen een Promise/CompletableFuturegebruiken om precies dat te doen: de CompletableFutureonmiddellijk, en roep complete(T result)aan zodra de berekening is voltooid.


Antwoord 4, autoriteit 61%

Ik zal een voorbeeld geven van wat Promise is en hoe de waarde ervan op elk moment kan worden ingesteld, in tegenstelling tot Future, welke waarde alleen leesbaar is.

Stel dat je een moeder hebt en je vraagt ​​haar om geld.

// 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); 

Uitvoer daarvan is:

Thank you mom for $10

Mama’s belofte is gemaakt, maar wachtte op een “voltooiing” -gebeurtenis.

CompletableFuture<Integer> promise...

Je hebt zo’n evenement gecreëerd, haar belofte geaccepteerd en je plannen aangekondigd om je moeder te bedanken:

promise.thenAccept...

Op dit moment begon moeder haar tas te openen…maar erg langzaam…

en vader kwam veel sneller tussenbeide en maakte de belofte waar in plaats van je moeder:

promise.complete(10);

Heb je een uitvoerder opgemerkt die ik expliciet heb geschreven?

Interessant is dat als je in plaats daarvan een standaard impliciete uitvoerder gebruikt (commonPool) en vader niet thuis is, maar alleen moeder met haar “trage portemonnee”, haar belofte alleen zal worden voltooid als het programma langer duurt dan moeder nodig heeft geld uit de portemonnee.

De standaarduitvoerder gedraagt ​​zich als een “daemon” en wacht niet tot alle beloften worden vervuld. Ik heb geen goede beschrijving van dit feit gevonden…


Antwoord 5, autoriteit 6%

Ik weet niet zeker of dit een antwoord kan zijn, maar als ik zie wat anderen over iemand hebben gezegd, kan het lijken alsof je twee afzonderlijke abstracties nodig hebt voor beide concepten, zodat een van hen (Future) is slechts een alleen-lezen weergave van de andere (Promise) … maar eigenlijk is dit niet nodig.

Kijk bijvoorbeeld eens hoe beloften worden gedefinieerd in javascript:

https://promisesaplus.com/

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

De focus ligt op de composability met behulp van de thenmethode zoals:

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);
})

waardoor asynchrone berekening eruitziet als synchroon:

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);
}

wat best cool is.
(Niet zo cool als async-awaitmaar async-awaitverwijdert gewoon de standaardtekst ….then(function(result) {….ervan).

En eigenlijk is hun abstractie best goed als de constructeur van de belofte

new Promise( function(resolve, reject) { /* do it */ } );

hiermee kun je twee callbacks geven die kunnen worden gebruikt om de Promisemet succes of met een fout af te ronden. Zodat alleen de code die de Promisemaakt deze kan voltooien en de code die een reeds geconstrueerd Promise-object ontvangt, de alleen-lezen weergave heeft.

Met overerving kan het bovenstaande worden bereikt als resolveen rejectbeschermde methoden zijn.


Antwoord 6, autoriteit 3%

Voor klantcode is Promise bedoeld om te observeren of terugbellen toe te voegen wanneer een resultaat beschikbaar is, terwijl Future is om op resultaat te wachten en dan verder te gaan. Theoretisch alles wat mogelijk is met futures wat kan met beloften, maar vanwege het stijlverschil maakt de resulterende API voor beloften in verschillende talen het ketenen gemakkelijker.


Antwoord 7

Geen vaste methode in toekomstige interface, alleen methode ophalen, dus het is alleen-lezen.
Over CompletableFuture, dit artikel is misschien nuttig.
completablefuture


Antwoord 8

Futureen Promisezijn proxy-object voor onbekend resultaat

Promisevoltooit een Future

  • Promise– schrijver/producent van onbekend resultaat.
  • Future– lezer/gebruiker met onbekend resultaat. Het heeft de volgende staten: in behandeling, vervuld, geannuleerd
//Future has a reference to Promise
Future -> Promise

Als producerpromiseiets en ben ik er verantwoordelijk voor

Als consumerdie een Promiseheeft nagekomen, verwacht ik in de Futureresultaat te hebben. In Futurekan ik de Promisegebruiken of afwijzen

Voor Java CompletableFuturesis het een Promiseomdat je het resultaat kunt instellen en het implementeert ook Future


Antwoord 9

In dit voorbeeldkunt u bekijken hoe Promises in Java kan worden gebruikt
voor het maken van asynchrone reeksen oproepen:

doSomeProcess()
    .whenResult(result -> System.out.println(String.format("Result of some process is '%s'", result)))
    .whenException(e -> System.out.println(String.format("Exception after some process is '%s'", e.getMessage())))
    .map(String::toLowerCase)
    .mapEx((result, e) -> e == null ? String.format("The mapped result is '%s'", result) : e.getMessage())
    .whenResult(s -> System.out.println(s));

Other episodes