차이 무엇 Future
과 Promise
?
둘 다 향후 결과를위한 자리 표시 자 역할을하지만 주요 차이점은 어디에 있습니까?
차이 무엇 Future
과 Promise
?
둘 다 향후 결과를위한 자리 표시 자 역할을하지만 주요 차이점은 어디에 있습니까?
답변:
이 토론 에 따르면 , Promise
마침내 CompletableFuture
Java 8에 포함되도록 요청되었으며 javadoc은 다음 과 같이 설명합니다.
명시 적으로 완료 될 수있는 (가치 및 상태 설정) 미래 완료시 트리거되는 종속 함수 및 조치를 지원하는 CompletionStage로 사용될 수 있습니다.
목록에 예가 있습니다.
f.then((s -> aStringFunction(s)).thenAsync(s -> ...);
최종 API는 약간 다르지만 비슷한 비동기 실행을 허용합니다.
CompletableFuture<String> f = ...;
f.thenApply(this::modifyString).thenAccept(System.out::println);
(지금까지 답변에 완전히 만족하지 않으므로 여기에 내 시도가 있습니다 ...)
케빈 라이트의 의견 ( "약속을 할 수 있고 그것을 지키는 것은 당신에게 달려 있습니다. 다른 누군가가 당신에게 약속을하면 미래에 그것을 존중하는지 기다릴 수 있도록 기다려야합니다" )는 요약하지만, 일부는 설명이 유용 할 수 있습니다.
미래와 약속 은 매우 유사한 개념이지만, 미래는 아직 존재하지 않는 결과에 대한 읽기 전용 컨테이너이며 약속은 작성할 수 있지만 (보통 한 번만) 차이가 있습니다. 자바 8 CompletableFuture 와 구아바 SettableFuture가 자신의 값 ( "완료")을 설정할 수 있기 때문에, 약속으로 생각하지만, 그들은 또한 미래의 인터페이스를 구현 할 수있다, 따라서 클라이언트에 대한 차이가 없다.
미래의 결과는 비동기 계산의 결과로 "다른 사람"에 의해 설정됩니다. 어떻게 참고 FutureTask 고전 미래가 - - 해야한다 주는, Callable 또는 Runnable를 사용하여 초기화 할 수는없는 인수 없음의 생성자가 없다, 그리고 미래와 FutureTask 모두 읽기 전용 외부에서 (FutureTask의 설정 방법은 보호)된다. 값은 내부에서 계산 한 결과로 설정됩니다.
다른 한편으로, 약속의 결과는 공개 세터 방법이 있기 때문에 언제라도 "귀하"(또는 사실상 누구에 의해)에 의해 설정 될 수 있습니다. CompletableFuture와 SettableFuture는 모두 작업없이 만들 수 있으며 언제든지 값을 설정할 수 있습니다. 클라이언트 코드에 약속을 보내고 나중에 원하는대로 이행하십시오.
CompletableFuture는 "순수한"약속이 아니며 FutureTask와 같은 작업으로 초기화 할 수 있으며 가장 유용한 기능은 처리 단계의 관련이없는 체인입니다.
또한 약속은 미래의 하위 유형일 필요는 없으며 동일한 객체 일 필요는 없습니다. 스칼라에서 미래 객체는 비동기 계산 또는 다른 Promise 객체에 의해 생성됩니다 . C ++에서는 상황이 비슷합니다. 프로 미스 오브젝트는 생산자가 사용하고 미래 오브젝트는 소비자가 사용합니다. 이 분리의 장점은 클라이언트가 미래의 가치를 설정할 수 없다는 것입니다.
Spring 과 EJB 3.1 에는 모두 Scala / C ++ 약속과 비슷한 AsyncResult 클래스가 있습니다. AsyncResult는 Future를 구현하지만 이것이 실제 미래는 아닙니다. Spring / EJB의 비동기 메소드는 배경 마술을 통해 다른 읽기 전용 Future 객체를 반환하며이 두 번째 "실제"미래는 클라이언트가 결과에 액세스하는 데 사용할 수 있습니다.
나는 이미 받아 들여진 대답이 있음을 알고 있지만 그럼에도 불구하고 내 2 센트를 추가하고 싶습니다.
TLDR : 미래와 약속은 비동기 작업의 두 가지 측면입니다 : 소비자 / 발신자 대 생산자 / 구현 자 .
비동기 API 메소드 의 호출자Future
로서 계산 결과에 대한 핸들로 얻을 수 있습니다. 예를 들어 get()
계산을 완료하고 결과를 검색 할 때까지 기다릴 수 있습니다 .
이제이 API 메소드가 실제로 어떻게 구현되는지 생각해보십시오. 구현 자는 Future
즉시 반환해야합니다 . 그들은 계산이 완료 되 자마자 그 미래를 완성 할 책임이 있습니다 (파견 논리를 구현하고 있기 때문에 알게 될 것입니다 ;-)). 그들은 Promise
/ CompletableFuture
를 사용하여 다음 을 수행합니다. CompletableFuture
즉시 구성하고 반환 complete(T result)
하고 계산이 완료되면 호출 합니다.
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) 아버지가 집에 있지 않고 "느린 지갑"을 가진 엄마 만 있다면, 프로그램이 엄마보다 돈을 벌어야하는 것보다 오래 살면 약속이 완료됩니다. 지갑.
기본 실행자는 "데몬"처럼 작동하며 모든 약속이 이행되기를 기다리지 않습니다. 나는이 사실에 대한 좋은 설명을 찾지 못했습니다 ...
이 대답을 할 수 있습니다 확실하지하지만 만약 내가 다른 사람들이 당신이이 개념을 모두 두 개의 별도의 추상화를 필요로처럼 (의 하나가 그래서 보일 수 있습니다 사람을 말한 참조로 Future
() 다른 단지 읽기 전용이다 Promise
) ...하지만 실제로는 필요하지 않습니다.
예를 들어 Javascript에서 약속이 어떻게 정의되는지 살펴보십시오.
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
객체 를받는 코드 는 읽기 전용보기를 갖습니다.
상속 상기 경우에 달성 될 수 결의 및 거부 의 보호 방법이다.
CompletableFuture
a와 비슷한 점이 Promise
있지만 소비하고자하는 방식이 다르기 때문에 여전히 a가 아닙니다Promise
. Promise
'의 결과는를 호출하여 소비되고 then(function)
함수는 생산자 호출 직후 생산자의 컨텍스트에서 실행 됩니다resolve
. Future
의 결과를 호출하여 소비 get
그리고, 제조자 스레드 값을 생성 할 때까지 대기하는 소비자 스레드 인해 소비자에 처리한다. Future
... 본질적으로 멀티 스레드,하지만
Promise
단일 스레드로만 사용할 수 있습니다 (실제로 원래 설계된 정확한 환경입니다 : 자바 스크립트 응용 프로그램에는 일반적으로 단일 스레드 만 있으므로 구현할 수 없습니다Future
). Promise
그러므로 훨씬 더 가볍고 효율적인 것보다 Future
,하지만 Future
더 복잡하고 쉽게 사용하여 배치 할 수 없습니다 스레드 간의 협력이 필요한 상황에서 도움이 될 수 Promise
들. 요약하면 : Promise
푸시 모델이며, 동안 Future
(관찰 가능한 대의 Iterable CF) 풀 모델입니다
XMLHttpRequest
). 나는 효율성 주장을 믿지 않습니다. 몇 가지 수치가 있습니까? +++ 아주 좋은 설명이었습니다.
get
, 해결되지 않은 호출 Future
에는 2 스레드 컨텍스트 스위치가 필요하며 적어도 몇 년 전 약 50 us 가 필요할 것으로 예상됩니다 .
Promise
그것을 만들 수 있으며 그것을 유지하는 것은 당신에게 달려 있습니다. 다른 사람이 당신에게 약속을하면 당신은 그들이 약속을 지키는 지 기다려야합니다.Future