Saya membaca SIP-14 dan konsepnya Future
masuk akal dan mudah dimengerti. Tapi punya dua pertanyaan tentang Promise
:
Kata SIP
Depending on the implementation, it may be the case that p.future == p
. Bagaimana ini bisa terjadi? AdalahFuture
danPromise
tidak dua jenis yang berbeda?Kapan sebaiknya kita menggunakan
Promise
?producer and consumer
Kode contoh :import scala.concurrent.{ future, promise } val p = promise[T] val f = p.future val producer = future { val r = produceSomething() p success r continueDoingSomethingUnrelated() } val consumer = future { startDoingSomething() f onSuccess { case r => doSomethingWithResult() } }
mudah dibaca tetapi apakah kita benar-benar perlu menulis seperti itu? Saya mencoba menerapkannya hanya dengan Future dan tanpa Promise seperti ini:
val f = future {
produceSomething()
}
val producer = future {
continueDoingSomethingUnrelated()
}
startDoingSomething()
val consumer = future {
f onSuccess {
case r => doSomethingWithResult()
}
}
Apa perbedaan antara ini dan contoh yang diberikan dan apa yang membuat Janji diperlukan?
scala
concurrency
xiefei
sumber
sumber
Future
danPromise
merupakan dua jenis yang berbeda, tetapi seperti yang Anda lihat dari github.com/scala/scala/blob/master/src/library/scala/concurrent/…Promise
implementasi khusus ini juga meluasFuture
.Jawaban:
Janji dan Masa Depan adalah konsep yang saling melengkapi. Masa Depan adalah nilai yang akan diambil, yah, suatu saat nanti dan Anda dapat melakukan banyak hal dengannya saat peristiwa itu terjadi. Oleh karena itu, ini adalah titik akhir pembacaan atau keluar dari sebuah komputasi - itu adalah sesuatu yang Anda ambil nilainya.
A Promise, dengan analogi, adalah sisi penulisan dari perhitungan. Anda membuat promise yang merupakan tempat Anda akan meletakkan hasil penghitungan dan dari promise tersebut Anda mendapatkan masa depan yang akan digunakan untuk membaca hasil yang dimasukkan ke dalam promise. Saat Anda akan menyelesaikan sebuah Janji, baik karena gagal atau berhasil, Anda akan memicu semua perilaku yang terkait dengan Masa Depan terkait.
Mengenai pertanyaan pertama Anda, bagaimana mungkin itu untuk janji yang kita miliki
p.future == p
. Anda dapat membayangkan ini seperti buffer satu item - sebuah wadah yang awalnya kosong dan Anda dapat menyimpan satu nilai yang akan menjadi isinya selamanya. Sekarang, tergantung pada sudut pandang Anda, ini adalah Janji dan Masa Depan. Ini adalah janji untuk seseorang yang berniat untuk menulis nilai di buffer. Ini adalah masa depan bagi seseorang yang menunggu nilai itu dimasukkan ke dalam buffer.Khususnya, untuk Scala concurrent API, jika Anda melihat sifat Promise di sini, Anda dapat melihat bagaimana metode dari objek pendamping Promise diimplementasikan:
object Promise { /** Creates a promise object which can be completed with a value. * * @tparam T the type of the value in the promise * @return the newly created `Promise` object */ def apply[T](): Promise[T] = new impl.Promise.DefaultPromise[T]() /** Creates an already completed Promise with the specified exception. * * @tparam T the type of the value in the promise * @return the newly created `Promise` object */ def failed[T](exception: Throwable): Promise[T] = new impl.Promise.KeptPromise[T](Failure(exception)) /** Creates an already completed Promise with the specified result. * * @tparam T the type of the value in the promise * @return the newly created `Promise` object */ def successful[T](result: T): Promise[T] = new impl.Promise.KeptPromise[T](Success(result)) }
Sekarang, implementasi dari promise, DefaultPromise dan KeptPromise dapat ditemukan di sini . Keduanya memperluas sifat kecil dasar yang kebetulan memiliki nama yang sama, tetapi terletak di paket yang berbeda:
private[concurrent] trait Promise[T] extends scala.concurrent.Promise[T] with scala.concurrent.Future[T] { def future: this.type = this }
Jadi Anda bisa melihat apa yang mereka maksud
p.future == p
.DefaultPromise
adalah buffer yang saya maksud di atas, sedangkanKeptPromise
buffer dengan nilai yang dimasukkan dari pembuatannya.Mengenai contoh Anda, blok masa depan yang Anda gunakan di sana sebenarnya menciptakan janji di balik layar. Mari kita lihat definisi
future
di sini :def future[T](body: =>T)(implicit execctx: ExecutionContext): Future[T] = Future[T](body)
Dengan mengikuti rantai metode Anda berakhir di impl.Future :
private[concurrent] object Future { class PromiseCompletingRunnable[T](body: => T) extends Runnable { val promise = new Promise.DefaultPromise[T]() override def run() = { promise complete { try Success(body) catch { case NonFatal(e) => Failure(e) } } } } def apply[T](body: =>T)(implicit executor: ExecutionContext): scala.concurrent.Future[T] = { val runnable = new PromiseCompletingRunnable(body) executor.execute(runnable) runnable.promise.future } }
Jadi, seperti yang Anda lihat, hasil yang Anda peroleh dari blok produser Anda dituangkan menjadi sebuah janji.
EDIT TERAKHIR :
Mengenai penggunaan dunia nyata: Seringkali Anda tidak akan berurusan dengan janji secara langsung. Jika Anda akan menggunakan pustaka yang melakukan komputasi asinkron, Anda hanya akan bekerja dengan masa depan yang dikembalikan oleh metode pustaka. Janji, dalam hal ini, dibuat oleh perpustakaan - Anda hanya bekerja dengan akhir membaca dari apa yang dilakukan metode tersebut.
Tetapi jika Anda perlu menerapkan API asinkron Anda sendiri, Anda harus mulai bekerja dengannya. Misalkan Anda perlu menerapkan klien HTTP asinkron di atas, katakanlah, Netty. Kemudian kode Anda akan terlihat seperti ini
def makeHTTPCall(request: Request): Future[Response] = { val p = Promise[Response] registerOnCompleteCallback(buffer => { val response = makeResponse(buffer) p success response }) p.future }
sumber
Promise
s harus dalam kode implementasi.Future
adalah hal yang bagus dan hanya-baca yang dapat Anda tampilkan ke kode klien. Selain itu,Future.future{...}
sintaks terkadang bisa merepotkan.def makeHTTPCall(request: Request): Future[Response] = { Future { registerOnCompleteCallback(buffer => { val response = makeResponse(buffer) response }) } }
registerOnCompleteCallback()
selesai. Juga, itu tidak kembaliFuture[Response]
. Ia kembaliFuture[registerOnCompleteCallback() return type]
sebagai gantinya.