Artikel ini terutama mempelajari contoh kode terkait dari teknologi komunikasi sinkronisasi utas tradisional dari konkurensi Java, sebagai berikut.
Mari kita lihat pertanyaan terlebih dahulu:
Ada dua utas. Utas anak dieksekusi 10 kali lebih dulu, kemudian utas utama dieksekusi 5 kali, kemudian beralih ke utas anak mengeksekusi 10, dan kemudian utas utama mengeksekusi 5 kali ... perjalanan pulang pergi ini 50 kali.
Setelah membaca pertanyaan ini, jelas bahwa komunikasi antara utas digunakan. Izinkan saya menganalisis ide terlebih dahulu: Pertama harus ada dua utas, dan kemudian harus ada 50 loop di setiap utas, karena setiap utas harus melakukan tugas 50 kali pulang pergi, tugas utas utama adalah untuk mengeksekusi 5 kali, dan tugas utas anak adalah untuk mengeksekusi 10 kali. Teknologi komunikasi antar-thread terutama menggunakan metode wait() dan metode notify() . Metode tunggu () menyebabkan utas saat ini menunggu dan melepaskan kunci yang ditahan. Metode notify() menunjukkan bahwa satu utas yang menunggu pada monitor objek ini dibangunkan. Mari kita selesaikan masalah komunikasi antar-thread ini langkah demi langkah.
Pertama, terlepas dari komunikasi antara utas utama dan utas anak, tulis tugas yang akan dieksekusi oleh setiap utas:
Kelas Publik TradisionalThreadCommunication {public static void main (string [] args) {// buka utas anak baru utas baru (runnable baru () {@Override public void run () {for (int i = 1; i <= 50; i ++) {Synchronized (TradisionalTreadCommunication.class) {/<= i ++ {System.out.println ("Urutan Sub Thread" +j +", loop" +i);}}}}}). Start (); // Metode utama adalah utas utama untuk (int i = 1; i <= 50; i ++) {Synchronized (TradisionalTrreadCommunication.class) {//Main; {System.out.println ("Urutan utas utama" + j + ", loop" + i);}}}}}}}}}}}}}}}}}}Seperti disebutkan di atas, kedua utas masing -masing memiliki 50 loop besar dan menjalankan 50 tugas, tugas utas anak dieksekusi 10 kali, dan tugas utas utama dieksekusi 5 kali. Untuk memastikan sinkronisasi antara dua utas, blok kode sinkronisasi yang disinkronkan digunakan, dan kunci yang sama digunakan: objek bytecode kelas. Ini memastikan keamanan utas. Tapi desain ini tidak terlalu bagus. Sama seperti yang saya tulis di kebuntuan di bagian sebelumnya, kita dapat memasukkan tugas utas ke dalam kelas. Pola desain ini lebih terstruktur, dan menempatkan tugas utas yang berbeda ke dalam kelas yang sama akan dengan mudah menyelesaikan masalah sinkronisasi karena mudah untuk menggunakan kunci yang sama di kelas. Jadi modifikasi program di atas:
Kelas publik TradisionalThreadCommunication {public static void main (string [] args) {bisnis bisnis = baru bisnis (); // baru kelas pemrosesan tugas utas // buka utas anak baru (runnable baru () {@override public run () {for (int i = 1; i <= 50; i ++ins) {Buss. Utas utama untuk (int i = 1; i <= 50; i ++) {Bussies.main (i);}}} // Data umum (termasuk kunci sinkronisasi) atau beberapa metode umum yang akan digunakan harus diklasifikasikan ke dalam kelas yang sama. Desain ini hanya mencerminkan ketahanan program pengelompokan kelas tinggi. BISNIS CLASS {public disinkronkan void sub (int i) {for (int j = 1; j <= 10; j ++) {System.out.println ("Sub Thread Urutan" +j +", loop" +i);}} public Synchronized void Main (int i) {for (int j = 1; j <= 5; j <= 5; j + ", loop" + i);}} Setelah modifikasi ini, struktur program menjadi lebih jelas dan lebih kuat. Cukup tambahkan kata kunci yang disinkronkan ke dua metode tugas utas, dan gunakan kunci ini. Tetapi belum ada komunikasi antara kedua utas tersebut. Hasil eksekusi adalah bahwa utas utama mengeluarkan tugas 50 kali, dan utas anak mengeluarkan tugas 50 kali. Alasannya sangat sederhana, karena ada sinkronisasi yang disinkronkan.
Berikut ini terus meningkatkan program untuk memungkinkan komunikasi antara kedua utas seperti yang dijelaskan dalam pertanyaan:
Kelas publik TradisionalThreadCommunication {public static void main (string [] args) {bisnis bisnis = baru bisnis (); // baru kelas pemrosesan tugas utas // buka utas anak baru (runnable baru () {@override public run () {for (int i = 1; i <= 50; i ++ins) {Buss. Thread utama untuk (int i = 1; i <= 50; i ++) {BusSiness.main (i);}}} // Untuk menggunakan data umum (termasuk kunci sinkronisasi) atau beberapa metode umum harus diklasifikasikan ke dalam kelas yang sama. Desain ini hanya mencerminkan ketahanan drama Gao Lei dan program. BISNIS CLASS {private boolean bshouldsub = true; public disinkronkan void sub (int i) {while (! bshouldsub) {// Jika bukan giliran Anda untuk dieksekusi, coba {this.wait (); // objek yang memanggil metode tunggu () harus sama dengan objek kunci yang disinkronkan. Di sini disinkronkan ada pada metode ini, jadi gunakan tangkapan} ini (interruptedException e) {// todo Auto-generated color blocke.printstacktrace ();}} for (int j = 1; j <= 10; j ++) {System.out.println ("Sub Thread Sequence of" + J + J ++, loop = loop); this.notify();//Wake up the main thread waiting}public synchronized void main(int i) {while(bShouldSub) {//If it is not your turn to execute, try {this.wait();}catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}for (int j = 1;j <= 5; j ++) {System.out.println ("Urutan utas utama" + j + ", loop" + i);} bshouldsub = true; // ubah tag this.notify (); // bangunkan utas anak yang menunggu}}Pertama-tama, jangan bicara tentang implementasi program spesifik, dari perspektif struktural, kami telah menyadari manfaat dari desain ini: tidak perlu memodifikasi apa pun dalam fungsi utama, dan logika tentang sinkronisasi antar-thread dan komunikasi antar-thread semuanya ada di kelas bisnis. Utas yang berbeda dalam fungsi utama hanya perlu memanggil tugas yang sesuai ditempatkan di kelas. Ini mencerminkan manfaat dari kombinasi tinggi.
Mari kita lihat kode tertentu lagi. Pertama, tentukan variabel boolean untuk mengidentifikasi utas mana yang harus dieksekusi. Ketika bukan utas anak, itu akan tidur. Maka secara alami akan menjalankan utas utama. Setelah eksekusi, itu akan memodifikasi Bshouldsub dan membangunkan utas anak. Pada saat ini, utas anak akan menilai bahwa sementara tidak puas dan tidak akan tidur. Ini akan menjalankan tugas utas anak. Demikian pula, setelah utas utama baru saja memodifikasi Bshouldsub, ketika loop kedua digunakan untuk menjalankan tugas utas utama, itu akan tidur dan menunggu utas anak untuk bangun. Ini membuat logikanya sangat jelas. Utas utama dan utas anak bergiliran untuk melaksanakan tugas masing -masing, dan ritme ini total 50 kali.
Ada penjelasan kecil lain: sebenarnya mungkin digunakan jika menilai, tetapi mengapa digunakan sementara? Karena kadang -kadang benang akan bangun dengan fakely (itu seperti berjalan tidur, yang jelas tidur tapi berdiri). Jika menggunakan IF, maka setelah itu Fakely bangun, itu tidak akan kembali untuk menilai jika, dan kemudian secara alami akan menjalankan tugas. Oke, utas lain sedang dieksekusi, dan itu akan mempengaruhi utas lain dalam sekejap. Tetapi jika itu lama, itu akan berbeda. Bahkan jika utasnya benar -benar terjaga, itu akan tetap menilai sementara. Namun, utas lainnya sedang dijalankan saat ini. Bshouldsub belum dimodifikasi, jadi masih masuk sementara dan sedang tidur lagi ~ jadi sangat aman dan tidak akan mempengaruhi utas lainnya! Ini juga dilakukan dalam dokumen JDK resmi.
Mari kita ringkas komunikasi antara utas.
Di atas adalah semua penjelasan terperinci dari kode teknologi komunikasi sinkronisasi tradisional Java Concurrency, dan saya harap ini akan membantu semua orang. Teman yang tertarik dapat terus merujuk ke topik terkait lainnya di situs ini. Jika ada kekurangan, silakan tinggalkan pesan untuk menunjukkannya. Terima kasih teman atas dukungan Anda untuk situs ini!