Apa perbedaan antara Future
dan Promise
?
Mereka berdua bertindak seperti pengganti untuk hasil masa depan, tetapi di mana perbedaan utama?
Apa perbedaan antara Future
dan Promise
?
Mereka berdua bertindak seperti pengganti untuk hasil masa depan, tetapi di mana perbedaan utama?
Jawaban:
Menurut diskusi ini , Promise
akhirnya telah dipanggil CompletableFuture
untuk dimasukkan dalam Java 8, dan javadoc-nya menjelaskan:
Masa Depan yang dapat diselesaikan secara eksplisit (menetapkan nilai dan statusnya), dan dapat digunakan sebagai CompletionStage, mendukung fungsi dan tindakan yang bergantung yang memicu penyelesaiannya.
Contoh juga diberikan dalam daftar:
f.then((s -> aStringFunction(s)).thenAsync(s -> ...);
Perhatikan bahwa API final sedikit berbeda tetapi memungkinkan eksekusi asinkron serupa:
CompletableFuture<String> f = ...;
f.thenApply(this::modifyString).thenAccept(System.out::println);
(Aku tidak sepenuhnya senang dengan jawaban sejauh ini, jadi ini usahaku ...)
Saya pikir komentar Kevin Wright ( "Anda bisa membuat Janji dan itu terserah Anda untuk menyimpannya. Ketika orang lain membuat Anda berjanji, Anda harus menunggu untuk melihat apakah mereka menghormatinya di Masa Depan" ) merangkumnya dengan cukup baik, tetapi beberapa Penjelasan bisa bermanfaat.
Berjangka dan janji adalah konsep yang sangat mirip, perbedaannya adalah bahwa masa depan adalah wadah baca-saja untuk hasil yang belum ada, sementara janji dapat ditulis (biasanya hanya sekali). Java 8 CompletableFuture dan Guava SettableFuture dapat dianggap sebagai janji, karena nilainya dapat diatur ("selesai"), tetapi mereka juga mengimplementasikan antarmuka Masa Depan, oleh karena itu tidak ada perbedaan untuk klien.
Hasil masa depan akan ditetapkan oleh "orang lain" - oleh hasil perhitungan yang tidak sinkron. Perhatikan bagaimana FutureTask - masa depan klasik - harus diinisialisasi dengan Callable atau Runnable, tidak ada konstruktor tanpa argumen, dan FutureTask dan FutureTask keduanya hanya-baca dari luar (metode yang ditetapkan FutureTask dilindungi). Nilai akan ditetapkan ke hasil perhitungan dari dalam.
Di sisi lain, hasil dari janji dapat ditetapkan oleh "Anda" (atau bahkan oleh siapa saja) kapan saja karena memiliki metode setter publik. CompletableFuture dan SettableFuture dapat dibuat tanpa tugas apa pun, dan nilainya dapat diatur kapan saja. Anda mengirim janji ke kode klien, dan memenuhinya nanti seperti yang Anda inginkan.
Perhatikan bahwa CompletableFuture bukan janji "murni", ia dapat diinisialisasi dengan tugas seperti FutureTask, dan fitur yang paling berguna adalah rantai proses langkah yang tidak terkait.
Juga perhatikan bahwa janji tidak harus menjadi subtipe masa depan dan tidak harus menjadi objek yang sama. Dalam Scala, objek Masa Depan dibuat oleh perhitungan asinkron atau oleh objek Janji yang berbeda . Dalam C ++ situasinya mirip: objek janji digunakan oleh produsen dan objek masa depan oleh konsumen. Keuntungan dari pemisahan ini adalah bahwa klien tidak dapat menetapkan nilai masa depan.
Baik Spring dan EJB 3.1 memiliki kelas AsyncResult, yang mirip dengan janji Scala / C ++. AsyncResult tidak mengimplementasikan Future tetapi ini bukan masa depan yang sebenarnya: metode asynchronous di Spring / EJB mengembalikan objek Future yang berbeda dan hanya-baca melalui beberapa sihir latar belakang, dan masa depan "nyata" kedua ini dapat digunakan oleh klien untuk mengakses hasilnya.
Saya sadar bahwa sudah ada jawaban yang diterima tetapi ingin menambahkan dua sen saya:
TLDR: Masa Depan dan Janji adalah dua sisi dari operasi asinkron: konsumen / pemanggil vs. produsen / implementor .
Sebagai pemanggil metode API asinkron, Anda akan mendapatkan Future
sebagai pegangan untuk hasil perhitungan. Anda dapat misalnya memanggilnya get()
untuk menunggu perhitungannya selesai dan mengambil hasilnya.
Sekarang pikirkan bagaimana metode API ini benar-benar diimplementasikan: Implementor harus Future
segera mengembalikan . Mereka bertanggung jawab untuk menyelesaikan masa depan itu segera setelah perhitungan dilakukan (yang akan mereka ketahui karena menerapkan logika pengiriman ;-)). Mereka akan menggunakan a Promise
/ CompletableFuture
untuk melakukan hal itu: Bangun dan kembalikan CompletableFuture
segera, dan panggil complete(T result)
setelah perhitungan selesai.
Saya akan memberikan contoh tentang apa itu Janji dan bagaimana nilainya dapat ditetapkan kapan saja, berlawanan dengan Masa Depan, yang nilainya hanya dapat dibaca.
Misalkan Anda memiliki seorang ibu dan Anda meminta uang kepadanya.
// 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);
Output dari itu adalah:
Thank you mom for $10
Janji Mom telah dibuat, tetapi menunggu beberapa acara "penyelesaian".
CompletableFuture<Integer> promise...
Anda membuat acara seperti itu, menerima janjinya dan mengumumkan rencana Anda untuk berterima kasih kepada ibumu:
promise.thenAccept...
Pada saat ini ibu mulai membuka dompetnya ... tetapi sangat lambat ...
dan ayah mencampuri lebih cepat dan menyelesaikan janjinya daripada ibumu:
promise.complete(10);
Pernahkah Anda memperhatikan seorang eksekutor yang saya tulis secara eksplisit?
Menariknya, jika Anda menggunakan pelaksana implisit default sebagai gantinya (commonPool) dan ayah tidak ada di rumah, tetapi hanya ibu yang memiliki "dompet lambat", maka janjinya hanya akan selesai, jika program ini hidup lebih lama dari yang dibutuhkan ibu untuk mendapatkan uang dari tas.
Eksekutor default bertindak seperti "daemon" dan tidak menunggu semua janji dipenuhi. Saya belum menemukan deskripsi yang baik tentang fakta ini ...
Tidak yakin apakah ini bisa menjadi jawaban tetapi ketika saya melihat apa yang dikatakan orang lain untuk seseorang, mungkin Anda membutuhkan dua abstraksi terpisah untuk kedua konsep ini sehingga salah satunya ( Future
) hanya merupakan tampilan hanya baca dari yang lain ( Promise
) ... tapi sebenarnya ini tidak diperlukan.
Sebagai contoh, lihat bagaimana janji-janji didefinisikan dalam javascript:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Fokusnya adalah pada kompabilitas menggunakan then
metode seperti:
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);
})
yang membuat perhitungan asinkron terlihat seperti sinkron:
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);
}
yang cukup keren. (Tidak sekeren async-tunggu tapi async-tunggu hanya menghilangkan boilerplate .... lalu (fungsi (hasil) {.... darinya).
Dan sebenarnya abstraksi mereka cukup bagus sebagai konstruktor janji
new Promise( function(resolve, reject) { /* do it */ } );
memungkinkan Anda untuk memberikan dua panggilan balik yang dapat digunakan untuk menyelesaikan dengan Promise
sukses atau dengan kesalahan. Sehingga hanya kode yang membuat Promise
bisa menyelesaikannya dan kode yang menerima objek yang sudah dibangun Promise
memiliki tampilan hanya baca.
Dengan warisan hal di atas dapat dicapai jika tekad dan penolakan adalah metode yang dilindungi.
CompletableFuture
mungkin memiliki beberapa kesamaan dengan Promise
tetapi itu tetap bukanPromise
, karena cara itu dimaksudkan untuk dikonsumsi berbeda: Promise
hasil a dikonsumsi oleh panggilan then(function)
, dan fungsi dieksekusi dalam konteks produsen segera setelah produsen memanggil resolve
. Hasil A Future
dikonsumsi dengan menelepon get
yang menyebabkan utas konsumen menunggu sampai utas produsen menghasilkan nilai, lalu memprosesnya di konsumen. Future
secara inheren multithreaded, tapi ...
Promise
hanya dengan satu utas (dan pada kenyataannya itulah lingkungan yang sebenarnya mereka dirancang untuk: aplikasi javascript umumnya hanya memiliki satu utas, sehingga Anda tidak dapat menerapkannya di Future
sana). Promise
Oleh karena itu jauh lebih ringan dan efisien daripada Future
, tetapi Future
dapat membantu dalam situasi yang lebih kompleks dan membutuhkan kerjasama antara benang yang tidak dapat dengan mudah diatur dengan menggunakan Promise
s. Untuk meringkas: Promise
adalah model dorong, sementara Future
adalah model tarikan (lih Iterable vs Observable)
XMLHttpRequest
). Saya tidak percaya klaim efisiensi, apakah Anda memiliki beberapa angka? +++ Konon, penjelasan yang sangat bagus.
get
yang belum terselesaikan Future
tentu akan melibatkan 2 sakelar konteks utas, yang setidaknya beberapa tahun lalu kemungkinan membutuhkan sekitar 50 kita .
Untuk kode klien, Janji adalah untuk mengamati atau melampirkan panggilan balik ketika suatu hasil tersedia, sedangkan Masa Depan adalah untuk menunggu hasil dan kemudian melanjutkan. Secara teoritis apa pun yang mungkin dilakukan dengan masa depan apa yang dapat dilakukan dengan janji, tetapi karena perbedaan gaya, API yang dihasilkan untuk janji dalam berbagai bahasa membuat rantai lebih mudah.
Tidak ada metode yang ditetapkan di antarmuka Masa Depan, hanya dapatkan metode, jadi ini hanya baca. Tentang CompletableFuture, artikel ini mungkin membantu. masa depan yang dapat diselesaikan
Promise
dan terserah Anda untuk menyimpannya. Ketika orang lain membuat Anda berjanji, Anda harus menunggu untuk melihat apakah mereka menghargainyaFuture