Hari ini kita akan belajar bagaimana melakukan pemrograman asinkron di musim semi. Kita semua tahu bahwa utas bahwa server web memproses request permintaan diperoleh dari kumpulan utas, yang tidak sulit untuk dijelaskan, karena ketika jumlah permintaan web sangat besar, bagaimana membuat utas pemrosesan ketika permintaan masuk. Karena overhead membuat utas dan switching konteks utas relatif besar, server web pada akhirnya akan menghadapi kerusakan. Selain itu, utas pemrosesan yang dibuat oleh server web dieksekusi secara serempak dari awal hingga akhir secara default. Dengan kata lain, jika pemrosesan utas A bertanggung jawab untuk memproses permintaan B, maka ketika B tidak return , memproses utas A tidak dapat melarikan diri untuk memproses permintaan lain, yang akan sangat membatasi kemampuan pemrosesan server web secara bersamaan.
Oleh karena itu, kumpulan utas memecahkan masalah daur ulang benang, jadi bagaimana cara menyelesaikan permintaan pemrosesan sinkron? Jawabannya adalah pemrosesan asinkron. Apa itu pemrosesan asinkron? Pemrosesan asinkron terutama memungkinkan permintaan B di atas untuk menganggur sebelum pemrosesan permintaan di atas selesai, dan utas A dapat dibebaskan untuk terus memproses permintaan lain. Kemudian kita dapat melakukan ini, restart Thread C di dalam utas A untuk menjalankan tugas, biarkan kembali langsung ke server web, dan terus menerima permintaan baru.
Sebelum memulai penjelasan di bawah ini, pertama -tama saya akan membedakan dua konsep di sini:
1. Proses utas
Utas pemrosesan milik server web, bertanggung jawab untuk memproses permintaan pengguna, dan dikelola berdasarkan kumpulan utas
2. Threading asinkron
Utas asinkron adalah utas yang ditentukan pengguna dan dapat dikelola oleh kumpulan utas.
Spring memberikan dukungan untuk tugas asinkron. Tugas asinkron dapat diimplementasikan menggunakan kelas WebAsyncTask . Pada saat yang sama, kami juga dapat mengatur pemrosesan panggilan balik yang sesuai untuk tugas -tugas asinkron, seperti cara menangani ketika tugas habis, dan cara melempar pengecualian. Tugas asinkron biasanya sangat praktis. Misalnya, kami ingin meninggalkan operasi yang dapat diproses untuk waktu yang lama ke utas asinkron untuk diproses, atau ketika pesanan dibayar, kami mengaktifkan tugas asinkron untuk menanyakan hasil pembayaran dari pesanan.
1. Tugas asinkron normal
Untuk kenyamanan demonstrasi, pelaksanaan tugas asinkron disimulasikan menggunakan Thread.sleep(long) . Sekarang asumsikan bahwa pengguna meminta antarmuka berikut:
http://localhost:7000/demo/getUserWithNoThing.json
Antarmuka tugas asinkron didefinisikan sebagai berikut:
/*** Uji tugas asinkron tanpa pengecualian*/@requestMapping (value = "getUserWithnothing.json", Method = requestMethod.get) public WebAsynctask <pangkik> getUserWithnothing () {// cetak name process.err.r.println ("nama utas utama" + +curr. // Ini mensimulasikan pembukaan tugas asinkron, dengan batas waktu 10s WebAsynctask <string> Task1 = WebAsynctask baru <string> (10 * 1000L, () -> {System.err.println ("NAMA TUGAS PERTAMA adalah" + Thread. Kembalikan "Tugas 1 dieksekusi dengan sukses! Tidak ada pengecualian yang dilemparkan!"; // Metode dipanggil ketika eksekusi tugas diselesaikan Task1.oncompletion (() -> {System.err.println ("Tugas 1 mengeksekusi selesai!");}); System.err.println ("Task1 terus menangani hal -hal lain!"); Return Task1;}Konsol mencetak sebagai berikut:
Nama utas utama adalah http-nio-7000-exec-1
Task1 terus berurusan dengan hal -hal lain!
Nama utas pertama adalah mvcasync1
Tugas 1 telah selesai!
Hasil browser adalah sebagai berikut:
2. Melampaui pengecualian tugas asinkron
Panggilan antarmuka: http://localhost:7000/demo/getUserWithError.json
/*** Uji tugas asinkron di mana kesalahan terjadi* @return*/ @requestMapping (value = "getUserWotherror.json", method = requestMethod.get) public WebAsynctask <string> getUserwitherror () {System.err.println ("nama utas utama" + utas. tugas asinkron. WebAsynctask <string> Task3 = WebAsynctask baru <string> (10 * 1000L, () -> {System.err.println ("Nama utas kedua adalah" + thread.currentThread (). GetName ()); // pengecualian yang dilemparkan ke sini num = 9/0; System.err.println (num); pengembalian "; task3.onerror (() -> {System.err.println ("======================================================================================================================================================================================== ======================================================================================================================================================= ======================================================================================================================================================= ====================================================================================================================================================================== "================================================================ =================================================================== =================================================================== =================================================================== =================================================================== =================================================================== =================================================================== ===================================================================Output konsol adalah sebagai berikut:
Nama utas utama adalah http-nio-7000-exec-1
Task3 terus berurusan dengan hal -hal lain!
Nama utas kedua adalah mvcasync1
2018-06-15 09: 40: 13.538 ERROR 9168 --- [NIO-7000-EXEC-2] OACCC [. [. [. [DispatcherServlet]: servlet.service () untuk servlet [DispatcherServlet] lemparan pengecualianjava.lang.arithmeticException: / by nol
di com.example.demo.controller.getUserInfocontroller.lambda $ 5 (getUserInfocontroller.java:93) ~ [kelas/: na]
di org.springframework.web.context.request.async.webasyncManager.lambda $ startCallableProcessing $ 4 (webasyncmanager.java:317) ~ [Spring-Web-5.0.6.release.jar: 5.0.6.release]]
di java.util.concurrent.executors $ runnableadapter.call (executors.java:511) ~ [na: 1.8.0_161]
di java.util.concurrent.futuretask.run (futuretask.java:266) ~ [na: 1.8.0_161]
di java.lang.thread.run (thread.java:748) [NA: 1.8.0_161]2018-06-15 09: 40: 13.539 ERROR 9168 --- [NIO-7000-EXEC-2] OACCC [. [. [. [DispatcherServlet]: Servlet.service () untuk Servlet [DispatcherServlet] dalam konteks dengan jalur [/demo] Lemparan Pengecualian [Pemrosesan Permintaan gagal; Pengecualian bersarang adalah java.lang.arithmeticexception: / by nol] dengan akar penyebab
java.lang.arithmeticException: / by nol
di com.example.demo.controller.getUserInfocontroller.lambda $ 5 (getUserInfocontroller.java:93) ~ [kelas/: na]
di org.springframework.web.context.request.async.webasyncManager.lambda $ startCallableProcessing $ 4 (webasyncmanager.java:317) ~ [Spring-Web-5.0.6.release.jar: 5.0.6.release]]
di java.util.concurrent.executors $ runnableadapter.call (executors.java:511) ~ [na: 1.8.0_161]
di java.util.concurrent.futuretask.run (futuretask.java:266) ~ [na: 1.8.0_161]
di java.lang.thread.run (thread.java:748) [NA: 1.8.0_161]=====================================================================================================================================================
Misi 3 telah terjadi!
Tugas 3 telah selesai!
Tentu saja, Anda juga dapat melakukan beberapa penanganan pengecualian pada hal di atas untuk menghindari pendapat pengguna yang tidak ramah. Untuk penanganan pengecualian, Anda dapat memeriksa artikel lain dalam artikel saya tentang penggunaan skema penanganan kesalahan boot spring/spring
Hasil Output Browser:
3. Tugas asinkron waktu
Panggilan antarmuka: http://localhost:7000/demo/getUserWithTimeOut.json
/*** Uji tugas asinkron di mana tugas waktunya habis* @return*/ @requestMapping (value = "getUserWithTimeOut.json", method = requestMethod.get) public WebAsynctask <string> getUserWithTimeOut () {System.err.println ("nama utas utama adalah" + utas. // Ini disimulasikan untuk memulai tugas asinkron, batas waktu 10s WebAsynctask <string> Tugas2 = WebAsynctask baru <String> (10 * 1000L, () -> {System.err.println ("NAMA UTAS KETIGA" "Utass. // Tugas Timeout Panggilan Metode ini Task2.onTimeout (() -> { System.err.println ("========================================================================================================================================================================================== ====================================================================================================================================================================== ====================================================================================================================================================================== ====================================================================================================================================================================== "================================================================ =================================================================== =================================================================== =================================================================== =================================================================== =================================================================== =================================================================== ===================================================================Hasil Eksekusi Konsol:
Nama utas utama adalah HTTP-NIO-7000-Exec-4
Task2 terus berurusan dengan hal -hal lain!
Nama utas kedua adalah mvcasync2
=============================================================================================================================================================
Tugas 2 telah selesai!
Hasil Eksekusi Browser:
4. Tugas Pool Thread Asinkron
Tugas asinkron dalam tiga kasus di atas tidak dikelola oleh mekanisme kumpulan utas secara default. Dengan kata lain, jika suatu permintaan masuk, meskipun utas pemrosesan dirilis, sistem masih akan membuat utas tugas asinkron untuk setiap permintaan, yang merupakan utas tugas asinkron yang dimulai dengan MvcAsync seperti yang kita lihat di atas. Artinya, ini tidak akan berhasil, overhead sangat tinggi! Oleh karena itu, kami dapat menggunakan kumpulan utas untuk manajemen dan secara langsung lulus instance objek ThreadPoolTaskExecutor dalam konstruktor kelas WebAsyncTask .
Pertama -tama mari kita lihat apa yang terjadi saat melakukan permintaan bersamaan dalam kasus pertama di atas (di sini kita mensimulasikan panggilan bersamaan ke http://localhost:7000/demo/getUserWithNoThing.json ):
Output konsol adalah sebagai berikut:
Nama utas pertama adalah mvcasync57
Nama utas pertama adalah mvcasync58
Nama utas pertama adalah mvcasync59
Nama utas pertama adalah mvcasync60
Nama utas pertama adalah mvcasync61
Nama utas pertama adalah mvcasync62
Nama utas pertama adalah mvcasync63
Nama utas pertama adalah mvcasync64
Nama utas pertama adalah mvcasync65
Nama utas pertama adalah mvcasync66
Nama utas pertama adalah mvcasync67
Nama utas pertama adalah mvcasync68
Nama utas pertama adalah mvcasync69
Nama utas pertama adalah mvcasync70
Nama utas pertama adalah mvcasync71
Nama utas pertama adalah mvcasync72
Nama utas pertama adalah mvcasync73
Nama utas pertama adalah mvcasync74
Nama utas pertama adalah mvcasync76
Nama utas pertama adalah mvcasync75
Nama utas pertama adalah mvcasync77
Nama utas pertama adalah mvcasync78
Nama utas pertama adalah mvcasync79
Nama utas pertama adalah mvcasync80
Karena kumpulan utas tidak ditambahkan, 100 permintaan akan membuka 100 utas tugas asinkron, yang sangat mahal dan tidak disarankan.
Berikut ini adalah implementasi kumpulan utas:
Antarmuka panggilan: http://localhost:7000/demo/getUserWithExecutor.json
/*** Uji kumpulan utas* @return*/ @requestMapping (value = "getUserWithExecutor.json", method = requestMethod.get) public WebAsynctask <string> getUserWithExecutor () {getName.RR.PRINTLN ("Nama utas utama adalah" + thread.currentThread (). GetName ();); // Ini disimulasikan untuk memulai tugas asinkron, dan kumpulan utas dilewatkan di sini. WebAsynctask <string> Task1 = WebAsynctask baru <string> (10 * 1000L, Executor, () -> {System.err.println ("Nama utas pertama adalah" + thread.currentThread (). GetName ()); thread.sleep (5000l); return "Tugas 4 Eksekusi berhasil! Tidak ada pengecualian! // Panggil metode ini ketika eksekusi tugas diselesaikan Task1.onCompletion (() -> {System.err.println ("Tugas 4 mengeksekusi selesai!");}); System.err.println ("Task4 terus menangani hal -hal lain!"); Return Task1;}Kumpulan utas didefinisikan sebagai berikut:
@ConfigurationPublic kelas myExecutor {@bean statis public threadpooltaskexecutor getExecutor () {threadpooltaskexecutor Taskexecutor = new ThreadPooltaskexecutor (); taskexecutor.setCorepoolSize (30); taskexecutor.setmaxpoolsize (30); taskexecutor.setqueuecapacity (50); taskexecutor.setThreadnameprefix ("huang"); // Nama utas tugas asinkron adalah Huang awalan kembali Taskexecutor; }}Tes bersamaan di atas dapat digunakan untuk mendapatkan hasil berikut:
Alamat kode sampel artikel ini: https://github.com/smallercoder/webasynctask
Menggunakan kumpulan utas dapat menyimpan sumber daya server dan mengoptimalkan kemampuan pemrosesan server. Ingatlah untuk sering menggunakannya! Terima kasih sudah membaca! Jika Anda pikir itu akan membantu Anda, silakan mulai!
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.