Cara menggunakan Akka Futures secara asinkron di Java

Saya melakukan panggilan di lapisan layanan Java yang terlihat seperti ini;

Future<Object> future = Patterns.ask(myActor, message, timeout);

Response res = (Response) Await.result(future, timeout.duration());

Saya telah membaca dokumentasi Akka dan menyadari bahwa pemblokiran seperti ini tidak disarankan. Saya perlu mengembalikan objek respons ke metode panggilan. Apakah mungkin melakukan ini secara asinkron dengan Akka dari layanan Java saya? Saya mencoba melakukan ini menggunakan metode future.onSuccess namun metode onSuccess tidak mengizinkan nilai pengembalian jadi saya tidak dapat mengembalikan nilainya.


person cdugga    schedule 20.08.2014    source sumber


Jawaban (1)


Cara akka meneruskan data antar utas, yang pada dasarnya adalah apa yang Anda lakukan dengan memblokir di atas adalah dengan membuat masa depan atau mengirim pesan ke Aktor.

Contoh berikut diambil dari dokumentasi Akka.

final ExecutionContext ec = system.dispatcher();

Future<String> f1 = future(new Callable<String>() {
    public String call() {
        return "Hello" + "World";
    }
}, ec);

Future<Integer> f2 = f1.map(new Mapper<String, Integer>() {
    public Integer apply(String s) {
        return s.length();
    }
}, ec);

f2.onSuccess(new PrintResult<Integer>(), system.dispatcher());

Perhatikan bahwa dalam contoh ini data sedang 'dikembalikan', atau lebih tepatnya sedang diserahkan ke unit kerja lain tanpa thread harus memblokir dan menunggu hasilnya.

Inilah sebabnya mengapa onSuccess mengembalikan batal, ini untuk digunakan di akhir rantai masa depan yang tersusun. Jika ingin mengembalikan suatu nilai, itu akan menjadi seperti peta dan akan mengembalikan Masa Depan yang lain. Yang akan membuat Anda memiliki persyaratan pemblokiran yang sama.

Jadi untuk menjawab pertanyaan Anda, tidak. Tidak ada cara untuk 'mengembalikan' nilai dari masa depan yang tidak sinkron tanpa pemblokiran. Sebaliknya Anda harus meninjau mengapa Anda memerlukan Response untuk dikembalikan seperti itu, dan melihat apakah Anda dapat memindahkan penanganan Response ke onSuccess atau map. Alternatif kecilnya adalah mengembalikan Future[Response] dan membiarkan penelepon khawatir tentang rangkaian masa depan. Kasus yang Anda alami biasanya terjadi ketika mencampurkan paradigma, dan sebaiknya dihindari.

person Chris K    schedule 20.08.2014
comment
panggilan yang diblokir dimulai ketika pengguna membuka layanan di situs web saya. Saya memblokir utas karena saya ingin respons terhadap permintaan berisi beberapa data untuk memperbarui UI. Bagaimana Anda menyarankan saya melakukan ini? - person cdugga; 21.08.2014
comment
@cdugga Kode GUI biasanya dirancang berdasarkan kelanjutan/panggilan balik, sehingga bagian itu harus mudah. Caranya biasanya pada bagian jaringan; jika kode jaringan dirancang untuk menjadi async (menggunakan futures dan nio) maka bingo. Kalau tidak, Anda tidak punya pilihan, Anda harus memblokir dan itulah yang saya maksud tentang pencampuran paradigma. Sebagian besar kode jaringan Java dirancang dengan model lama yang memiliki satu model thread dan blok, dan ketika jenis kode tersebut dicampur dengan Akka maka kita harus memblokirnya di suatu tempat. Cobalah untuk meminimalkannya dan menyimpannya di satu atau dua tempat. - person Chris K; 21.08.2014
comment
@cdugga ketika saya bekerja dengan klien yang memiliki jenis kode ini, dan basis kode terlalu besar untuk beralih ke solusi yang benar-benar async sekaligus maka saya cenderung memulai dari lapisan paling bawah dan mulai mengubah DAO dll dari mengembalikan DTO ke Masa Depan[DTO]. Saat antarmuka ini melintasi ranah non-asinkron, ada blok. Seiring waktu saya mendorongnya lebih tinggi dan lebih tinggi hingga mencapai kode jaringan, dan kemudian langkah terakhir adalah menukar perpustakaan jaringan dengan perpustakaan async. - person Chris K; 21.08.2014
comment
@cdugga kemungkinan lain yang sering terjadi adalah ketika panggilan db atau layanan web menggunakan api pemblokiran; dalam hal ini Masa Depan atau Aktor dapat digunakan untuk membungkus api tersebut dan dapat ditetapkan satu thread dari kumpulan thread global Akka. Dengan demikian membuat API pemblokiran tampak tidak memblokir Akka, dan menghindari polusi kumpulan thread global yang dapat menyebabkan kinerja tidak menentu di masa depan yang cepat dan pada tingkat ekstrem Akka dapat terkunci. - person Chris K; 21.08.2014