Pertanyaan Persediaan CompletableFutureAsync


Saya baru saja mulai menjelajahi beberapa fitur konkret Java 8. Satu hal yang membuat saya bingung adalah dua metode statis ini:

CompletableFuture<Void> runAsync(Runnable runnable) 
CompletableFuture<U> supplyAsync(Supplier<U> supplier)

Apakah ada yang tahu mengapa mereka memilih untuk menggunakan Pemasok antarmuka? Bukankah lebih alami menggunakan Callable, yang merupakan analogi dari Runnable yang mengembalikan nilai? Apakah itu karena Pemasok tidak membuang Pengecualian yang tidak bisa ditangani?


16
2018-03-28 05:09


asal


Jawaban:


Jawaban singkat

Tidak, itu tidak lebih alami untuk digunakan Callable dari pada Supplier di CompletableFuture.supplyAsync. Argumennya hampir sepenuhnya tentang semantik, jadi tidak apa-apa jika Anda masih merasa tidak yakin sesudahnya.

Jawaban panjang

Itu Callable dan Supplier antarmuka fungsional / tipe SAM praktis setara dalam fungsi (maafkan kata-kata), tetapi asal mereka dan penggunaan yang dimaksudkan berbeda.

Callable dibuat sebagai bagian dari java.util.concurrent paket. Paket itu datang sebelum perubahan besar di sekitar ekspresi lambda di Java 8 dan awalnya berkonsentrasi pada berbagai alat yang membantu Anda menulis kode bersamaan, tanpa banyak menyimpang dari model klasik multithreading langsung.

Tujuan utama dari Callable adalah untuk abstrak tindakan yang dapat dieksekusi dalam utas yang berbeda dan yang mengembalikan hasil. Dari CallableJavadoc:

Itu Callable antarmuka mirip dengan Runnable, dalam keduanya   dirancang untuk kelas yang instancenya berpotensi dieksekusi oleh   utas lagi.

Supplier dibuat sebagai bagian dari java.util.function paket. Paket itu datang sebagai bagian integral dari perubahan yang disebutkan di Java 8. Ini menyediakan jenis fungsional umum yang dapat ditargetkan oleh ekspresi lambda dan referensi metode.

Salah satu tipe tersebut adalah fungsi tanpa parameter yang mengembalikan hasil (yaitu fungsi yang mensuplai beberapa tipe atau a Supplier fungsi).

Jadi kenapa Supplier dan tidak Callable?

CompletableFuture merupakan bagian dari tambahan java.util.concurrent paket yang terinspirasi oleh perubahan-perubahan yang disebutkan di Java 8 dan yang memungkinkan pengembang untuk membangun kodenya secara fungsional, secara implisit paralel, bukannya secara eksplisit menangani konkurensi di dalamnya.

Nya supplyAsync metode membutuhkan cara untuk memberikan hasil dari tipe tertentu dan lebih tertarik pada hasil ini, dan bukan dalam tindakan yang diambil untuk mencapai hasil ini. Itu juga tidak peduli tentang penyelesaian yang luar biasa (juga lihat Bagaimana tentang... paragraf di bawah).

Tetap saja, jika Runnable digunakan untuk tanpa parameter, antarmuka fungsional tanpa hasil, seharusnya tidak Callable digunakan untuk tanpa parameter, antarmuka fungsional hasil tunggal?

Belum tentu.

Sebuah abstraksi untuk fungsi yang tidak memiliki parameter dan tidak mengembalikan hasil (dan karena itu beroperasi sepenuhnya melalui efek samping pada konteks luar) tidak termasuk dalam java.util.function. Ini berarti (agak mengganggu) Runnable digunakan di mana saja seperti antarmuka fungsional diperlukan.

Bagaimana dengan yang diperiksa Exception yang bisa dilemparkanCallable.call()?

Ini adalah tanda kecil dari perbedaan semantik yang dimaksudkan antara Callable dan Supplier.

SEBUAH Callable adalah tindakan yang dapat dieksekusi di utas lain, dan yang memungkinkan Anda untuk memeriksa efek sampingnya sebagai akibat dari pelaksanaannya. Jika semua berjalan dengan baik, Anda mendapatkan hasil dari tipe tertentu, tetapi karena situasi yang luar biasa dapat muncul ketika melakukan beberapa tindakan (terutama dalam konteks multithread), Anda mungkin juga ingin mendefinisikan dan menangani situasi yang luar biasa seperti itu.

SEBUAH Supplier di sisi lain adalah fungsi yang Anda andalkan untuk mensuplai objek dari beberapa tipe. Situasi luar biasa seharusnya tidak perlu dijadikan tanggung jawab Anda sebagai konsumen langsung dari Supplier. Ini karena:

  1. ... antarmuka fungsional sering digunakan untuk menentukan tahap tertentu dalam proses multi-tahap untuk membuat atau memutasi data, dan penanganan Exceptions bisa menjadi tahap terpisah, jika Anda peduli
  2. ... secara eksplisit menangani Exceptions secara signifikan mengurangi kekuatan ekspresif dari antarmuka fungsional, ekspresi lambda dan referensi metode

8
2018-04-01 10:59