Thread sering terlibat dalam pekerjaan. Misalnya, beberapa tugas sering diserahkan ke utas untuk eksekusi asinkron. Atau program server membuat tugas pemrosesan utas terpisah untuk setiap permintaan. Di luar utas, seperti koneksi database yang kami gunakan. Operasi penciptaan, penghancuran atau pembukaan dan penutupan ini memiliki dampak besar pada kinerja sistem. Oleh karena itu, penggunaan "biliar" disorot.
1. Mengapa menggunakan kumpulan benang
Dalam implementasi yang dijelaskan dalam Bagian 3.6.1, utas pekerja baru ditugaskan untuk setiap klien. Ketika utas pekerja berkomunikasi dengan klien, utasnya dihancurkan. Metode implementasi ini memiliki kekurangan berikut:
• Overhead pembuatan dan penghancuran server (termasuk sumber daya waktu dan sistem) sangat tinggi. Item ini tidak perlu dijelaskan, Anda dapat memeriksa "proses pembuatan utas". Selain pekerjaan yang dilakukan oleh mesin itu sendiri, kita juga perlu membuat instansi dan memulai, yang semuanya membutuhkan hunian sumber daya tumpukan.
• Selain overhead membuat dan menghancurkan utas, utas aktif juga mengkonsumsi sumber daya sistem. Ini harus menjadi konsumsi sumber daya tumpukan. Ini juga dianggap menebak jumlah koneksi basis data.
• Jika jumlah utas diperbaiki dan setiap utas memiliki siklus deklarasi yang panjang, maka switching utas juga relatif diperbaiki. Sistem operasi yang berbeda memiliki siklus switching yang berbeda, biasanya sekitar 20ms. Sakelar yang disebutkan di sini adalah untuk mentransfer hak penggunaan CPU antara utas di bawah penjadwalan JVM dan sistem operasi yang mendasarinya. Jika utas sering dibuat dan dihancurkan, utas akan sering diaktifkan, karena setelah utas dihancurkan, hak untuk digunakan harus diberikan ke utas siap, sehingga utas bisa mendapatkan kesempatan untuk berjalan. Dalam hal ini, switching antara utas tidak mengikuti siklus switching tetap sistem, dan overhead utas switching bahkan lebih besar dari overhead penciptaan dan penghancuran.
Secara relatif, menggunakan kumpulan benang, beberapa utas telah dibuat sebelumnya, yang terus-menerus menghapus tugas dari antrian kerja dan kemudian menjalankan tugas. Ketika utas pekerja menyelesaikan satu tugas, itu terus melaksanakan tugas lain dalam antrian kerja. Keuntungannya adalah sebagai berikut:
• Mengurangi jumlah penciptaan dan kehancuran, dan setiap utas pekerja dapat digunakan kembali sepanjang waktu dan dapat melakukan banyak tugas.
• Jumlah utas dalam kumpulan utas dapat dengan mudah disesuaikan sesuai dengan daya dukung sistem untuk mencegah kerusakan sistem karena sumber daya sistem yang berlebihan.
2. Implementasi sederhana dari kumpulan utas
Di bawah ini adalah kumpulan utas sederhana yang ditulis sendiri, yang juga langsung diambil dari buku pemrograman Java Network
Paket utas; impor java.util.linkedlist;/*** Implementasi kumpulan utas, berdasarkan panjang, panjang maksimum, dan panjang antrian kumpulan utas reguler, kita dapat meningkatkan jumlah implementasi* @author han*/mytreadpool kelas publik memperluas threadgroup {// cpu nomor --- runtime.getrunte (). // apakah akan menutup boolean pribadi isclosed = false; // Antrian Private LinkedList <Runnable> WorkQueue; // ID kumpulan utas private static int threadpoolid; private int threadid; public mythreadpool (int poolsize) {super ("mythreadpool."+threadpoolid); ThreadPoolid ++; setdaemon (true); workqueue = new LinkedList <Runnable> (); untuk (int i = 0; i <poolSize; i ++) {new workthread (). start (); }} // Di sini Anda dapat mengubah ke concurrentLinkedQueue untuk menghindari efisiensi menggunakan void execute yang disinkronkan publik yang disinkronkan (tugas runnable) {if (isclosed) {melempar IllegalStateException baru ("Pool koneksi telah ditutup ..."); } else {workqueue.add (tugas); memberitahu(); }} Dilindungi yang disinkronkan runnable getTask () melempar interruptedException {while (workqueue.size () == 0) {if (isClosed) {return null; } Tunggu(); } return workqueue.removefirst (); } public disinkronkan void close () {if (! isclosed) {isClosed = true; workqueue.clear (); mengganggu(); }} public void join () {disinkronkan (this) {isClosed = true; notifyall (); } Utas [] utas = utas baru [activeCount ()]; int count = alimerate (utas); untuk (int i = 0; i <count; i ++) {coba {threads [i] .join (); } catch (exception e) {}}} class workthread memperluas thread {public workThread () {super (mythreadpool.hiS, "workthread"+(threadId ++)); System.out.println ("Buat ..."); } @Override public void run () {while (! IsInterrupted ()) {System.out.println ("run .."); Runnable Task = null; Coba {// Ini adalah Tugas Metode Pemblokiran = GetTask (); } catch (Exception e) {} if (Task! = null) {Task.run (); } else {break; }}}}}}Kumpulan utas ini terutama mendefinisikan antrian kerja dan beberapa utas yang telah dibuat sebelumnya. Selama metode eksekusi dipanggil, Anda dapat mengirimkan tugas ke utas.
Ketika tidak ada tugas, utas berikutnya akan diblokir di gettask () sampai tugas baru masuk dan dibangunkan.
Baik bergabung dan dekat dapat digunakan untuk menutup kumpulan utas. Perbedaannya adalah bahwa bergabung akan menyelesaikan tugas dalam antrian, sementara Close akan segera menghapus antrian dan mengganggu semua utas pekerja. Interrupt () in close () setara dengan memanggil masing -masing interupsi () yang mengandung utas anak di threadgroup. Oleh karena itu, ketika utas menunggu atau tidur, interruptException akan dilemparkan.
Kelas tes adalah sebagai berikut:
TestMyThreadPool kelas publik {public static void main (string [] args) melempar interruptedException {mythreadpool pool = mythreadpool baru (3); untuk (int i = 0; i <10; i ++) {pool.execute (runnable baru () {@Override public void run () {coba {thread.sleep (1000);} catch (interruptedException e) {} system.out.println ("working ...");}}); } pool.join (); //pool.close (); }}3. Kolam utas yang disediakan oleh Perpustakaan Kelas JDK
Java menyediakan implementasi kumpulan utas yang baik, yang lebih kuat dan efisien daripada implementasi kami sendiri, dan juga memiliki fungsi yang lebih kuat.
Diagram kelas adalah sebagai berikut:
Para senior telah memberikan penjelasan yang bagus tentang jenis kumpulan utas ini. Setiap kumpulan utas Java di bawah Baidu memiliki contoh dan tutorial yang sangat rinci yang ditulis, jadi saya tidak akan mengulanginya di sini.
4. Kolam Benang Injeksi Musim Semi
Saat menggunakan kerangka kerja Spring, jika kami menggunakan metode yang disediakan oleh Java untuk membuat kumpulan utas, sangat tidak nyaman untuk dikelola dalam aplikasi multi-utas dan tidak sesuai dengan ide kami menggunakan Spring. (Meskipun musim semi dapat disuntikkan dengan metode statis)
Faktanya, Spring sendiri juga memberikan implementasi kumpulan utas yang baik. Kelas ini disebut ThreadPooltaskExecutor.
Konfigurasi di musim semi adalah sebagai berikut:
<bean id = "ExecutorService"> <name properti = "corePoolSize" value = "$ {threadpool.corepoolSize}" /> <!-Jumlah minimum utas yang dikelola oleh utas kumpulan-> <nama properti = "Keepaliveseconds" value = "$ {threadpool.eepalivesEconds} <! name = "maxPoolSize" value = "$ {threadpool.maxpoolSize}" /> <!-Jumlah maksimum utas yang dikelola oleh Thread Pool-> <properti name = "queuecapacity" value = "$ {threadpool.queueCapacity}" /> <!-Queue buffer yang digunakan oleh threadpool-queueCapacity} " /<!-Queue buffer yang digunakan oleh thread-thread-queueCapacity}" /<!5. Catatan tentang Menggunakan Kolam Benang
•Jalan buntu
Setiap program multithreaded berisiko mendadak. Kasing yang paling sederhana adalah bahwa dua utas AB, A Holds Lock 1, Request Lock 2, B Holds Lock 2, dan permintaan kunci 1. (Situasi ini juga akan muncul di MySQL Exclusive Lock, dan database akan secara langsung melaporkan pesan kesalahan). Ada kebuntuan lain di kumpulan utas: dengan asumsi bahwa semua utas pekerja di kumpulan utas diblokir saat menjalankan tugas masing -masing, dan mereka menunggu hasil eksekusi dari tugas tertentu A. Tugas A ada dalam antrian dan tidak dapat dieksekusi karena tidak ada utas idle. Dengan cara ini, semua sumber daya kumpulan utas akan diblokir dan kebuntuan akan dihasilkan.
• Sumber daya sistem yang tidak mencukupi
Jika jumlah utas dalam kumpulan utas sangat besar, utas ini akan mengkonsumsi sejumlah besar sumber daya, termasuk memori dan sumber daya sistem lainnya, yang secara serius mempengaruhi kinerja sistem.
• Kesalahan bersamaan
Antrian kerja dari kumpulan utas bergantung pada metode tunggu () dan memberi tahu () untuk memungkinkan pekerja mendapatkan tugas secara tepat waktu, tetapi kedua metode ini sulit digunakan. Jika kode salah, pemberitahuan mungkin hilang, menyebabkan utas pekerja tetap diam, mengabaikan tugas -tugas yang perlu diproses dalam antrian kerja. Karena yang terbaik adalah menggunakan beberapa kumpulan benang yang lebih dewasa.
• Kebocoran utas
Risiko serius menggunakan kumpulan benang adalah kebocoran benang. Untuk kumpulan utas dengan jumlah utas pekerja yang tetap, jika utas pekerja melempar runtimeException atau kesalahan saat menjalankan tugas, dan pengecualian atau kesalahan ini tidak tertangkap, utas pekerja berakhir secara tidak normal, menyebabkan kumpulan utas kehilangan utas secara permanen. (Ini sangat menarik)
Situasi lain adalah bahwa utas pekerja diblokir saat menjalankan tugas. Jika menunggu data input pengguna, tetapi pengguna tidak memasukkan data, menghasilkan utas yang diblokir sepanjang waktu. Utas pekerja seperti itu hanya dalam nama, dan sebenarnya tidak melakukan tugas apa pun. Jika semua utas di kumpulan utas dalam keadaan ini, kumpulan utas tidak dapat menambahkan tugas baru.
• Kelebihan tugas
Ketika ada sejumlah besar tugas yang antri untuk dieksekusi dalam antrian utas pekerja, tugas -tugas ini sendiri dapat mengkonsumsi terlalu banyak sumber daya sistem dan menyebabkan kekurangan sumber daya.
Singkatnya, saat menggunakan kumpulan utas, prinsip -prinsip berikut harus diikuti:
1. Jika tugas A perlu menunggu hasil eksekusi dari tugas B secara serempak selama eksekusi, maka tugas A tidak cocok untuk ditambahkan ke antrian kerja kumpulan utas. Jika Anda perlu menunggu tugas lain untuk menjalankan hasil seperti tugas A untuk ditambahkan ke antrian, itu dapat menyebabkan kebuntuan
2. Jika suatu tugas dapat diblokir dan diblokir untuk waktu yang lama, waktu batas waktu harus diatur untuk menghindari pemblokiran permanen dari utas pekerja dan menyebabkan kebocoran benang. Dalam program server, ketika utas menunggu klien terhubung atau menunggu data yang dikirim oleh klien, itu dapat menyebabkan penyumbatan. Anda dapat mengatur waktu dengan cara berikut:
Hubungi metode SetSoTimeout dari ServerSocket untuk mengatur waktu batas waktu untuk menunggu klien terhubung.
Untuk setiap soket yang terhubung ke pelanggan, hubungi metode setSoTimeout soket untuk mengatur waktu batas waktu menunggu pelanggan mengirim data.
3. Memahami karakteristik tugas dan menganalisis apakah tugas melakukan operasi yang sering memblokir operasi IO, atau melakukan operasi yang tidak akan memblokir. Yang pertama menempati CPU sebentar -sebentar, sedangkan yang terakhir memiliki tingkat pemanfaatan yang lebih tinggi. Berapa lama waktu yang dibutuhkan untuk menyelesaikan tugas? Apakah ini tugas jangka pendek atau tugas jangka panjang? Kemudian, klasifikasi tugas sesuai dengan karakteristik tugas, dan kemudian tambahkan berbagai jenis tugas ke antrian kerja dari berbagai kumpulan utas. Dengan cara ini, setiap kumpulan utas dapat dialokasikan dan disesuaikan sesuai dengan karakteristik tugas.
4. Ubah Ubah Ubah Kolam Benang. Ukuran optimal kumpulan utas terutama tergantung pada jumlah CPU yang tersedia dalam sistem dan karakteristik tugas dalam antrian kerja. Jika hanya ada satu antrian kerja pada sistem dengan N CPU, dan semuanya adalah tugas dengan sifat aritmatika (tidak memblokir), maka ketika kumpulan utas memiliki utas pekerja N atau N+1, penggunaan CPU maksimum umumnya akan diperoleh.
Jika antrian kerja berisi tugas yang melakukan operasi IO dan sering memblokir, buat ukuran kumpulan utas melebihi jumlah CPU yang tersedia, karena tidak semua utas kerja bekerja sepanjang waktu. Pilih tugas khas dan kemudian perkirakan rasio waktu tunggu dengan waktu yang benar -benar menempati CPU untuk melakukan operasi dalam proyek yang melakukan tugas ini. Untuk sistem dengan N utas CPU, kira -kira n*(1+wt/st) perlu diatur untuk memastikan bahwa CPU sepenuhnya digunakan.
Tentu saja, pemanfaatan CPU bukan satu -satunya hal yang perlu dipertimbangkan dalam proses menyesuaikan kumpulan benang. Ketika jumlah pekerjaan kumpulan utas meningkat, memori atau pembatasan sumber daya lainnya juga akan terjadi, seperti soket, pegangan file terbuka atau koneksi basis data, dll. Penting untuk memastikan bahwa sumber daya sistem yang dikonsumsi oleh multithread berada dalam ruang lingkup daya tahan sistem.
5. Hindari kelebihan tugas. Server harus membatasi jumlah koneksi bersamaan pelanggan berdasarkan kapasitas dukung sistem. Ketika koneksi klien melebihi nilai batas, server dapat menolak koneksi dan membuat permintaan yang ramah, atau membatasi panjang antrian.
Di atas beberapa metode implementasi dan jawaban untuk kumpulan utas Java adalah semua konten yang telah saya bagikan dengan Anda. Saya harap Anda dapat memberi Anda referensi dan saya harap Anda dapat mendukung wulin.com lebih lanjut.