Teman -teman yang telah menggunakan paket konkurensi Java mungkin terbiasa dengan masa depan (antarmuka). Masa depan bahkan didukung secara langsung pada tingkat sintaks dalam beberapa bahasa domain (seperti Alice ML).
Di sini kita akan mengambil java.util.concurrent.future sebagai contoh untuk berbicara secara singkat tentang metode kerja spesifik di masa depan. Objek masa depan itu sendiri dapat dianggap sebagai referensi eksplisit, referensi ke hasil pemrosesan asinkron. Karena sifatnya yang asinkron, objek yang dirujuknya mungkin tidak tersedia pada awal penciptaan (misalnya, masih dalam operasi, transmisi jaringan atau menunggu). Pada saat ini, jika aliran program yang menjadi masa depan tidak terburu -buru untuk menggunakan objek yang dirujuk oleh masa depan, maka ia dapat melakukan hal lain yang Anda inginkan. menjadi dua situasi:
Saya berharap dapat melihat objek ini tersedia dan menyelesaikan beberapa proses tindak lanjut terkait. Jika benar -benar tidak tersedia, Anda juga dapat memasuki proses cabang lainnya.
"Tanpa kamu, hidupku akan kehilangan artinya, jadi bahkan jika laut hilang, aku akan menunggumu." -waktu)
Untuk kasus sebelumnya, Anda dapat menentukan apakah objek yang direferensikan siap dengan menelepon Future.isdone () dan mengambil pemrosesan yang berbeda;
Dapatkan (waktu lama, unit TimeUnit) menunggu objek siap dengan pemblokiran sinkron. Apakah runtime yang sebenarnya diblokir atau dikembalikan segera tergantung pada waktu panggilan get () dan urutan objek siap.
Sederhananya, mode masa depan dapat memenuhi kebutuhan konkurensi berbasis data dalam proses berkelanjutan, tidak hanya mendapatkan peningkatan kinerja dalam eksekusi bersamaan, tetapi juga kesederhanaan dan keanggunan proses berkelanjutan.
Perbandingan dengan pola desain bersamaan lainnya
Selain di masa depan, pola desain konkurensi umum lainnya termasuk "Callback Driven (dalam lingkungan multi-threaded)", "Pesan/Event didorong (dalam model aktor)", dll.
Callback adalah mode konkurensi asinkron yang paling umum, yang memiliki kedekatan tinggi dan desain antarmuka sederhana. Tetapi dibandingkan dengan masa depan, kelemahannya juga sangat jelas. Pertama, callback di lingkungan multithreaded umumnya dieksekusi dalam utas modul yang memicu panggilan balik, yang berarti bahwa masalah eksklusi timbal balik harus dipertimbangkan saat menulis metode panggilan balik; Jalankan panggilan balik untuk aplikasi pengguna, yang juga relatif tidak aman, karena Anda tidak dapat menentukan berapa lama waktu yang dibutuhkan atau pengecualian apa yang akan terjadi, yang dapat secara tidak langsung mempengaruhi kedekatan dan keandalan modul ini; Urutan. Oleh karena itu, antarmuka callback cocok untuk skenario di mana hanya tugas sederhana yang perlu diselesaikan dalam panggilan balik dan tidak harus dikombinasikan dengan proses lain.
Kerugian dari mode panggilan balik di atas adalah kekuatan masa depan yang tepat. Karena penggunaan masa depan adalah untuk secara alami memasukkan driver data asinkron ke dalam proses berurutan, Anda tidak perlu mempertimbangkan masalah mutex utas sama sekali. disebutkan di bawah ini "Masa Masa Malas"). Di sisi lain, modul yang menyediakan antarmuka di masa depan tidak perlu khawatir tentang masalah keandalan seperti antarmuka callback dan dampak kedekatan potensial mereka pada modul ini.
Pola desain bersamaan yang umum lainnya adalah "Pesan (peristiwa) didorong", yang umumnya digunakan dalam model aktor: Pemohon Layanan mengirimkan pesan ke penyedia layanan, dan kemudian terus melakukan tugas -tugas berikutnya yang tidak bergantung pada hasil pemrosesan layanan layanan layanan layanan layanan layanan , dan tergantung padanya jika Anda perlu mengandalkannya. Meskipun kontrol bersamaan berbasis mesin negara bagian ini lebih cocok untuk proses sekuensial kontinuitas daripada panggilan balik, pengembang harus memotong proses berkelanjutan menjadi beberapa subproses spesifik negara bagian sesuai dengan panggilan layanan asinkron, yang secara artifisial meningkatkan kompleksitas pengembangan. Menggunakan Mode Masa Depan dapat menghindari masalah ini dan tidak perlu memutus proses berkelanjutan untuk panggilan asinkron. Namun, satu hal yang harus dicatat: Metode Future.get () dapat memblokir eksekusi utas, sehingga biasanya tidak dapat secara langsung dimasukkan ke dalam model aktor konvensional. (Model aktor yang berbasis di Coroutine dapat menyelesaikan konflik ini dengan lebih baik)
Fleksibilitas masa depan juga tercermin dalam pilihan bebas antara sinkronisasi dan pilihan asinkron. kebutuhan proses. Misalnya, Anda dapat memutuskan apakah akan menggunakan celah ini untuk menyelesaikan tugas -tugas lain berdasarkan apakah data siap, yang cukup nyaman untuk mengimplementasikan mekanisme "prediksi cabang asinkron".
Turunan masa depan
Selain bentuk -bentuk dasar yang disebutkan di atas, masa depan juga memiliki perubahan turunan yang kaya, jadi di sini ada beberapa yang umum.
Masa depan malas
Tidak seperti umum berjangka, masa depan malas tidak secara aktif mulai mempersiapkan objek yang direferensikan pada awal penciptaan, tetapi menunggu sampai objek diminta sebelum memulai pekerjaan yang sesuai. Oleh karena itu, masa depan malas itu sendiri tidak dimaksudkan untuk mencapai konkurensi, tetapi membutuhkan sumber daya komputasi yang tidak perlu sebagai titik awal, dan efeknya mirip dengan lambda/penutupan. Misalnya, ketika merancang API tertentu, Anda mungkin perlu mengembalikan serangkaian informasi, dan perhitungan beberapa di antaranya dapat mengkonsumsi sumber daya yang cukup besar. Namun, penelepon mungkin tidak peduli tentang semua informasi ini, sehingga menyediakan objek yang membutuhkan lebih banyak sumber daya dalam bentuk masa depan malas dapat menghemat sumber daya ketika penelepon tidak perlu menggunakan informasi spesifik.
Selain itu, masa depan malas juga dapat digunakan untuk menghindari pengecualian timbal balik yang tidak perlu yang disebabkan oleh akuisisi dini atau penguncian sumber daya.
Janji
Janji dapat dianggap sebagai cabang khusus di masa depan. Tetapi janji digunakan untuk secara eksplisit mewakili skenario di mana proses asinkron tidak secara langsung dipicu oleh penelepon layanan. Misalnya, kontrol waktu antarmuka di masa depan, proses asinkronnya tidak dipicu oleh penelepon, tetapi oleh jam sistem. Pelanggan, tetapi oleh pelanggan. Kapan penerbit akan mempublikasikan atau memperbarui data. Oleh karena itu, dibandingkan dengan masa depan standar, antarmuka janji umumnya memiliki antarmuka set tambahan () atau memenuhi ().
Masa depan yang dapat digunakan kembali
Masa depan yang teratur adalah satu kali, yang berarti bahwa ketika Anda mendapatkan hasil pemrosesan yang tidak sinkron, objek masa depan itu sendiri kehilangan maknanya. Tetapi masa depan yang dirancang khusus juga dapat digunakan kembali, yang sangat berguna untuk data yang dapat diubah beberapa kali. Misalnya, antarmuka gaya masa depan yang disediakan oleh kerangka kerja berlangganan yang didistribusikan Taobao yang disebutkan di atas memungkinkan beberapa panggilan untuk WaitNext () (setara dengan Future.get ()). Panggilan terakhir. Keuntungan dari desain ini adalah bahwa pengguna antarmuka dapat menanggapi perubahan data berlangganan pada waktu yang tepat, atau hanya melalui loop tak terbatas di utas independen, sementara juga memperhitungkan tugas waktu lainnya, atau bahkan menunggu beberapa tugas pada saat yang sama. Contoh yang disederhanakan adalah sebagai berikut:
untuk (;;) {jadwal = getNextScheduledTaskTime (); .}} doscheduledTask ();} Penggunaan masa depan
Pertama, mari kita daftar sepotong kode dalam pemikiran di Java.
//: concurrency/callabledemo.javaimport java.util.concurrent.*; impor java.util.*; TaskWithResult mengimplementasikan Callable <string> {private int id; String call () {return "Hasil dari TaskWithResult" + ID; NEW ARRAYLIST <Future <string> (); untuk (int i = 0; i <10; i ++) hasil. mencoba : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::::::::::::::::::::::: {// get () blok hingga penyelesaian: System.out.println (fs.get ()) ; ?Untuk menjelaskan penggunaan Masa Depan, Pertama, metode ExecorService Object Call Call () untuk menghasilkan objek di masa depan, yang menggunakan jenis spesifik dari hasil pengembalian yang dapat dipanggil untuk parameterisasi. Anda dapat menggunakan metode isDone () untuk menanyakan apakah masa depan telah selesai. Ketika tugas selesai, ia memiliki hasil, dan Anda dapat memanggil metode GET () untuk mendapatkan hasilnya. Anda juga dapat menghubungi GET () secara langsung tanpa pemeriksaan isdone (). Anda dapat memanggil fungsi get () dengan batas waktu, atau menelepon isDone () terlebih dahulu untuk melihat apakah tugas selesai, dan kemudian hubungi get ().