미래와 약속의 차이점은 무엇입니까?


274

차이 무엇 FuturePromise?
둘 다 향후 결과를위한 자리 표시 자 역할을하지만 주요 차이점은 어디에 있습니까?


99
당신은 Promise그것을 만들 수 있으며 그것을 유지하는 것은 당신에게 달려 있습니다. 다른 사람이 당신에게 약속을하면 당신은 그들이 약속을 지키는 지 기다려야합니다.Future
Kevin Wright


30
내가 읽은 가장 도움이되는 위키피디아 기사 중 하나
Fulluphigh

답변:


145

이 토론 에 따르면 , Promise마침내 CompletableFutureJava 8에 포함되도록 요청되었으며 javadoc은 다음 과 같이 설명합니다.

명시 적으로 완료 될 수있는 (가치 및 상태 설정) 미래 완료시 트리거되는 종속 함수 및 조치를 지원하는 CompletionStage로 사용될 수 있습니다.

목록에 예가 있습니다.

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

최종 API는 약간 다르지만 비슷한 비동기 실행을 허용합니다.

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

78
그것은 당신의 잘못 Assylias가 아니지만, javadoc 추출물은 괜찮은 기술 저자의 진지한 작업이 필요합니다. 5 번째 독해 과정에서 나는 그것이 말하려는 것을 이해하기 시작할 수 있습니다 ... 그리고 나는 이미 자리 잡은 미래와 약속을 이해하면서 이것에 도달합니다!
비트 뿌리 비트 뿌리

2
@ 비트 루트-비트 루트는 지금까지 일어난 것으로 보인다.
herman

1
@herman Thanks-javadoc의 최종 버전을 가리 키도록 링크를 업데이트했습니다.
assylias

7
@ Beetroot-Beetroot 예외적으로 메소드에 대해서는 문서를 확인해야합니다. 그것은 훌륭한시를 만들 것이지만, 읽을 수있는 문서의 예외적 인 실패입니다.
Fulluphigh

4
궁금한 사람은 @Fulluphigh가 이것을 언급하고 있습니다. 이 제거처럼 보인다는 / 자바 8에 정밀 검사
세드릭의 Reichenbach

148

(지금까지 답변에 완전히 만족하지 않으므로 여기에 내 시도가 있습니다 ...)

케빈 라이트의 의견 ( "약속을 할 수 있고 그것을 지키는 것은 당신에게 달려 있습니다. 다른 누군가가 당신에게 약속을하면 미래에 그것을 존중하는지 기다릴 수 있도록 기다려야합니다" )는 요약하지만, 일부는 설명이 유용 할 수 있습니다.

미래와 약속 은 매우 유사한 개념이지만, 미래는 아직 존재하지 않는 결과에 대한 읽기 전용 컨테이너이며 약속은 작성할 수 있지만 (보통 한 번만) 차이가 있습니다. 자바 8 CompletableFuture 와 구아바 SettableFuture가 자신의 값 ( "완료")을 설정할 수 있기 때문에, 약속으로 생각하지만, 그들은 또한 미래의 인터페이스를 구현 할 수있다, 따라서 클라이언트에 대한 차이가 없다.

미래의 결과는 비동기 계산의 결과로 "다른 사람"에 의해 설정됩니다. 어떻게 참고 FutureTask 고전 미래가 - - 해야한다 주는, Callable 또는 Runnable를 사용하여 초기화 할 수는없는 인수 없음의 생성자가 없다, 그리고 미래와 FutureTask 모두 읽기 전용 외부에서 (FutureTask의 설정 방법은 보호)된다. 값은 내부에서 계산 한 결과로 설정됩니다.

다른 한편으로, 약속의 결과는 공개 세터 방법이 있기 때문에 언제라도 "귀하"(또는 사실상 누구에 의해)에 의해 설정 될 수 있습니다. CompletableFuture와 SettableFuture는 모두 작업없이 만들 수 있으며 언제든지 값을 설정할 수 있습니다. 클라이언트 코드에 약속을 보내고 나중에 원하는대로 이행하십시오.

CompletableFuture는 "순수한"약속이 아니며 FutureTask와 같은 작업으로 초기화 할 수 있으며 가장 유용한 기능은 처리 단계의 관련이없는 체인입니다.

또한 약속은 미래의 하위 유형일 필요는 없으며 동일한 객체 일 필요는 없습니다. 스칼라에서 미래 객체는 비동기 계산 또는 다른 Promise 객체에 의해 생성됩니다 . C ++에서는 상황이 비슷합니다. 프로 미스 오브젝트는 생산자가 사용하고 미래 오브젝트는 소비자가 사용합니다. 이 분리의 장점은 클라이언트가 미래의 가치를 설정할 수 없다는 것입니다.

SpringEJB 3.1 에는 모두 Scala / C ++ 약속과 비슷한 AsyncResult 클래스가 있습니다. AsyncResult는 Future를 구현하지만 이것이 실제 미래는 아닙니다. Spring / EJB의 비동기 메소드는 배경 마술을 통해 다른 읽기 전용 Future 객체를 반환하며이 두 번째 "실제"미래는 클라이언트가 결과에 액세스하는 데 사용할 수 있습니다.


116

나는 이미 받아 들여진 대답이 있음을 알고 있지만 그럼에도 불구하고 내 2 센트를 추가하고 싶습니다.

TLDR : 미래와 약속은 비동기 작업의 두 가지 측면입니다 : 소비자 / 발신자생산자 / 구현 자 .

비동기 API 메소드 의 호출자Future 로서 계산 결과에 대한 핸들로 얻을 수 있습니다. 예를 들어 get()계산을 완료하고 결과를 검색 할 때까지 기다릴 수 있습니다 .

이제이 API 메소드가 실제로 어떻게 구현되는지 생각해보십시오. 구현 자는 Future즉시 반환해야합니다 . 그들은 계산이 완료 되 자마자 그 미래를 완성 할 책임이 있습니다 (파견 논리를 구현하고 있기 때문에 알게 될 것입니다 ;-)). 그들은 Promise/ CompletableFuture를 사용하여 다음 을 수행합니다. CompletableFuture즉시 구성하고 반환 complete(T result)하고 계산이 완료되면 호출 합니다.


1
이것은 약속이 항상 미래의 하위 클래스이며 미래의 작성 가능성이 유형에 의해 가려진다는 것을 의미합니까?
devios1

나는 그것이 암시 적이 라고 생각하지 않습니다 . 구현 측면에서는 종종 그렇습니다 (예 : Java, Scala).
Rahel Lüthy

74

Promise가 무엇인지, 그리고 그 값을 읽을 수만있는 Future와는 반대로 언제라도 그 값을 설정할 수있는 방법에 대한 예를 들겠습니다.

엄마가 있고 돈을 요구한다고 가정 해 봅시다.

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

내가 명시 적으로 작성한 유언 집행 인을 눈치 채 셨나요?

흥미롭게도, 기본 암시 적 executor를 대신 사용하고 (commonPool) 아버지가 집에 있지 않고 "느린 지갑"을 가진 엄마 만 있다면, 프로그램이 엄마보다 돈을 벌어야하는 것보다 오래 살면 약속이 완료됩니다. 지갑.

기본 실행자는 "데몬"처럼 작동하며 모든 약속이 이행되기를 기다리지 않습니다. 나는이 사실에 대한 좋은 설명을 찾지 못했습니다 ...


8
이 책을 읽는 것은 정말 재미있다! 나는 미래를 잊고 더 이상 약속 할 수 없다고 생각합니다.
user1532146

2
이것은 답변으로 받아 들여 져야합니다. 이야기를 읽는 것과 같습니다. 감사합니다 @Vladimir
Phillen

감사합니다 @Vladimir
intvprep

9

이 대답을 할 수 있습니다 확실하지하지만 만약 내가 다른 사람들이 당신이이 개념을 모두 두 개의 별도의 추상화를 필요로처럼 (의 하나가 그래서 보일 수 있습니다 사람을 말한 참조로 Future() 다른 단지 읽기 전용이다 Promise) ...하지만 실제로는 필요하지 않습니다.

예를 들어 Javascript에서 약속이 어떻게 정의되는지 살펴보십시오.

https://promisesaplus.com/

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-await 만큼 시원 하지는 않지만 async-await 는 상용구를 제거합니다 .... then (function (result) {.... ).

실제로 그들의 추상화는 약속 생성자로 꽤 좋습니다.

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

Promise성공적으로 완료하거나 오류와 함께 사용할 수있는 두 개의 콜백을 제공 할 수 있습니다 . 따라서 코드를 구성하는 코드 만 코드를 Promise완성 할 수 있으며 이미 생성 된 Promise객체 를받는 코드 는 읽기 전용보기를 갖습니다.

상속 상기 경우에 달성 될 수 결의거부 의 보호 방법이다.


4
+1. 이것이이 질문에 대한 정답입니다. CompletableFuturea와 비슷한 점이 Promise있지만 소비하고자하는 방식이 다르기 때문에 여전히 a가 아닙니다Promise . Promise'의 결과는를 호출하여 소비되고 then(function)함수는 생산자 호출 직후 생산자의 컨텍스트에서 실행 됩니다resolve . Future의 결과를 호출하여 소비 get그리고, 제조자 스레드 값을 생성 할 때까지 대기하는 소비자 스레드 인해 소비자에 처리한다. Future... 본질적으로 멀티 스레드,하지만
Periata Breatta

5
... Promise단일 스레드로만 사용할 수 있습니다 (실제로 원래 설계된 정확한 환경입니다 : 자바 스크립트 응용 프로그램에는 일반적으로 단일 스레드 만 있으므로 구현할 수 없습니다Future ). Promise그러므로 훨씬 더 가볍고 효율적인 것보다 Future,하지만 Future더 복잡하고 쉽게 사용하여 배치 할 수 없습니다 스레드 간의 협력이 필요한 상황에서 도움이 될 수 Promise들. 요약하면 : Promise푸시 모델이며, 동안 Future(관찰 가능한 대의 Iterable CF) 풀 모델입니다
Periata Breatta

@PeriataBreatta 단일 스레드 환경에서도 약속을 충족시키는 무언가가 있어야합니다 (일반적으로 다른 스레드로 실행됩니다 (예 :) XMLHttpRequest). 나는 효율성 주장을 믿지 않습니다. 몇 가지 수치가 있습니까? +++ 아주 좋은 설명이었습니다.
maaartinus 님이

1
@maaartinus-예, 약속을 이행해야하지만 외부 상태의 변화를 폴링하고 완료 된 조치와 관련된 약속을 해결하는 최상위 루프를 사용하여 수행 할 수 있습니다 (실제로 많은 경우). 효율성 측면에서는 구체적으로 약속에 대한 확실한 수치는 없지만 get, 해결되지 않은 호출 Future에는 2 스레드 컨텍스트 스위치가 필요하며 적어도 몇 년 전 약 50 us 가 필요할 것으로 예상됩니다 .
Periata Breatta

@PeriataBreatta 사실 귀하의 의견은 받아 들여질 솔루션이어야합니다. 나는 당신과 같은 설명 (풀 / 푸시, 단일 / 멀티 스레드)을 찾고있었습니다.
Thomas Jacob

5

클라이언트 코드의 경우 Promise는 결과를 사용할 수있을 때 콜백을 관찰하거나 첨부하는 반면 Future는 결과를 기다렸다가 계속하는 것입니다. 이론적으로는 약속으로 할 수있는 일과 선물로 할 수있는 모든 것이 있지만 스타일 차이로 인해 다른 언어로 된 약속에 대한 결과 API는 체인을 더 쉽게 만듭니다.


2

Future 인터페이스에는 set 메소드가없고 get 메소드 만 있으므로 읽기 전용입니다. CompletableFuture에 대해이 기사가 도움이 될 수 있습니다. 완성 할 수있는

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.