Kolam benang ialah alat, tetapi ia tidak sesuai untuk semua senario. Apabila menggunakan kumpulan benang, kita perlu mengkonfigurasinya dengan sewajarnya berdasarkan sifat aplikasi, ketersediaan sumber pengkomputeran dan keperluan aplikasi. Jika kumpulan benang dikonfigurasikan secara tidak betul, ia boleh menyebabkan kemerosotan prestasi aplikasi atau masalah seperti kebuntuan dan kebuluran. Oleh itu, kita perlu memilih kolam benang dengan berhati-hati.
Gunakan kumpulan benang untuk mengoptimumkan senario penggunaan aplikasi
Sebilangan besar tugasan jangka pendek: Jika aplikasi perlu mengendalikan sejumlah besar tugas jangka pendek, Menggunakan kumpulan benang boleh mengelakkan penciptaan dan pemusnahan benang yang kerap, dengan itu mengurangkan overhed penukaran konteks benang dan meningkatkan prestasi aplikasi dan kebolehskalaan.
Akses serentak kepada pangkalan data: Jika aplikasi perlu mengakses pangkalan data secara serentak, menggunakan kumpulan benang boleh menggunakan sepenuhnya kuasa pengkomputeran CPU berbilang teras dan meningkatkan prestasi dan daya pemprosesan akses serentak kepada pangkalan data.
Tugas intensif pengkomputeran: Jika aplikasi perlu melaksanakan tugas intensif pengkomputeran, kumpulan benang boleh digunakan untuk melaksanakan tugas secara serentak, menggunakan sepenuhnya kuasa pengkomputeran berbilang CPU teras dan mempertingkatkan prestasi dan tindak balas intensif pengkomputeran.
Aplikasi dipacu peristiwa: Jika aplikasi dipacu peristiwa, menggunakan kumpulan benang boleh mengelakkan urutan pemprosesan acara daripada disekat dan meningkatkan kelajuan tindak balas dan daya pemprosesan acara.
Tugas yang berjalan lama: Jika aplikasi perlu mengendalikan tugasan yang berjalan lama, menggunakan kumpulan benang boleh mengelakkan daripada menduduki sumber benang untuk masa yang lama dan meningkatkan ketersediaan dan kebolehskalaan aplikasi .
Konfigurasi kumpulan benang yang berbeza, dalam keadaan apakah ia harus digunakan:
1.FixedThreadPool
FixedThreadPool ialah Kumpulan benang bersaiz tetap yang pra-membuat bilangan benang tertentu apabila ia dibuat. Apabila tugasan perlu dilaksanakan, kumpulan utas akan memilih utas yang tersedia untuk melaksanakan tugas itu. Jika semua utas sedang melaksanakan tugas, tugasan baharu akan menunggu dalam baris gilir tugas.
Apabila menggunakan FixedThreadPool, perkara utama yang perlu dipertimbangkan ialah saiz kumpulan benang. Jika saiz kumpulan benang terlalu kecil, ia boleh menyebabkan tugasan dibariskan dalam baris gilir menunggu, yang menjejaskan masa tindak balas aplikasi. Jika saiz kumpulan benang terlalu besar, ia mungkin menggunakan terlalu banyak sumber pengkomputeran dan menyebabkan prestasi aplikasi merosot. Oleh itu, apabila memilih saiz kolam benang, anda perlu mempertimbangkan keperluan pengkomputeran aplikasi anda dan ketersediaan sumber pengkomputeran.
2.CachedThreadPool
CachedThreadPool ialah kumpulan benang bersaiz dinamik yang melaraskan saiz kumpulan benang secara automatik berdasarkan bilangan tugas. Apabila tugasan perlu dilaksanakan, kumpulan utas akan mencipta utas baharu untuk melaksanakan tugas itu. Jika terdapat berbilang tugasan yang perlu dilakukan, kumpulan benang akan mencipta berbilang benang. Apabila benang melahu, kumpulan benang akan mengitar semula benang ini.
CachedThreadPool sesuai untuk senario di mana sejumlah besar tugas perlu dilakukan dalam tempoh yang singkat. Memandangkan ia boleh melaraskan saiz kumpulan benang secara dinamik berdasarkan bilangan tugas, ia boleh menggunakan sumber pengkomputeran dengan lebih baik, dengan itu meningkatkan prestasi aplikasi.
3.SingleThreadExecutor
SingleThreadExecutor ialah kumpulan thread dengan hanya satu thread. Apabila tugasan perlu dilaksanakan, kumpulan benang akan menggunakan benang unik untuk melaksanakan tugas itu. Jika terdapat berbilang tugasan yang perlu dilaksanakan, mereka akan menunggu dalam baris gilir tugas. Memandangkan hanya terdapat satu urutan, SingleThreadExecutor sesuai untuk senario yang memerlukan pelaksanaan tugas yang berurutan, seperti kumpulan sambungan pangkalan data atau pemproses log.
4.ScheduledThreadPool
ScheduledThreadPool ialah kumpulan benang yang digunakan untuk melaksanakan tugas yang dijadualkan. Ia boleh melaksanakan tugas pada selang waktu tertentu atau selepas kelewatan tetap. Sebagai contoh, anda boleh menggunakan ScheduledThreadPool untuk kerap menyandarkan pangkalan data anda atau membersihkan log anda.
Apabila menggunakan ScheduledThreadPool, anda perlu memberi perhatian kepada masa pelaksanaan tugas dan pengulangan tugas. Jika sesuatu tugasan mengambil masa yang lama untuk dilaksanakan, ia mungkin menjejaskan masa pelaksanaan tugasan lain. Jika tugasan tidak berulang, anda mungkin perlu membatalkan tugasan secara manual untuk mengelakkan tugasan daripada diteruskan.
5.WorkStealingThreadPool
WorkStealingThreadPool ialah kumpulan benang yang menggunakan algoritma mencuri kerja. Ia menggunakan berbilang kumpulan benang, setiap satu dengan baris gilir tugas. Apabila benang dalam kumpulan benang melahu, ia mencuri tugas daripada baris gilir tugas dalam kumpulan benang lain untuk dilaksanakan.
WorkStealingThreadPool sesuai untuk senario di mana pelbagai tugas bebas perlu dilaksanakan. Memandangkan ia memperuntukkan tugas dan utas secara dinamik, ia membolehkan penggunaan sumber pengkomputeran yang lebih baik, dengan itu meningkatkan prestasi aplikasi.
Di atas ialah beberapa kumpulan benang yang biasa digunakan Sudah tentu, Java juga menyediakan kumpulan benang lain, seperti ForkJoinPool, CachedThreadExecutor, dll. Apabila memilih kumpulan benang, kita perlu membuat pilihan berdasarkan keperluan aplikasi dan ketersediaan sumber pengkomputeran.
Sesuaikan penciptaan kumpulan benang
Gunakan kelas kilang Executors untuk mencipta kumpulan benang. Walaupun kaedah ini mudah dan pantas, kadangkala kita perlu mengawal tingkah laku kumpulan benang dengan lebih tepat, dan kemudian kita perlu mencipta kumpulan benang tersuai.
Kolam benang dalam Java dilaksanakan melalui kelas ThreadPoolExecutor, jadi kami boleh menyesuaikan kumpulan benang dengan mencipta objek ThreadPoolExecutor. Kaedah pembina kelas ThreadPoolExecutor mempunyai berbilang parameter Di sini kami hanya memperkenalkan beberapa parameter yang biasa digunakan.
corePoolSize: Bilangan utas teras dalam kumpulan benang, iaitu bilangan minimum utas yang kekal aktif dalam kumpulan benang. Apabila tugasan diserahkan, jika bilangan utas aktif kurang daripada bilangan utas teras, utas baharu akan dibuat untuk memproses tugasan.
maximumPoolSize: Bilangan maksimum benang yang dibenarkan dalam kumpulan benang. Apabila tugasan diserahkan, jika bilangan utas aktif telah mencapai bilangan utas teras dan baris gilir tugasan penuh, utas baharu akan dibuat untuk memproses tugas sehingga bilangan utas aktif mencapai bilangan maksimum utas.
keepAliveTime: Masa urutan terbiar bagi urutan bukan teras kekal aktif. Apabila bilangan utas aktif lebih besar daripada bilangan utas teras, dan masa hidup utas terbiar melebihi keepAliveTime, ia akan dimusnahkan sehingga bilangan utas aktif tidak melebihi bilangan utas teras.
workQueue: Barisan tugas, digunakan untuk menyimpan tugasan yang menunggu untuk dilaksanakan. Java menyediakan pelbagai jenis baris gilir tugas, seperti SynchronousQueue, LinkedBlockingQueue, ArrayBlockingQueue, dll.
threadFactory: digunakan untuk mencipta utas baharu. Anda boleh menyesuaikan kaedah penciptaan benang dengan melaksanakan antara muka ThreadFactory, seperti menetapkan nama benang, menetapkan keutamaan benang, dsb.
Kolam benang yang dibuat secara tersuai boleh mengawal gelagat kumpulan benang dengan lebih fleksibel, seperti melaraskan bilangan utas teras dan bilangan maksimum utas mengikut senario aplikasi yang berbeza, memilih jenis yang berbeza barisan tugas, dsb. Pada masa yang sama, anda juga perlu memberi perhatian kepada prinsip reka bentuk kumpulan benang untuk mengelak daripada mencipta terlalu banyak benang, mengakibatkan pembaziran sumber sistem atau persaingan benang yang membawa kepada kemerosotan prestasi.
Strategi pengoptimuman kumpulan benang Gunakan kumpulan benang untuk mengoptimumkan prestasi aplikasi Anda perlu memberi perhatian kepada beberapa strategi pengoptimuman, termasuk saiz kumpulan benang, jenis baris gilir tugas, pengendalian pengecualian kumpulan benang, pemantauan kumpulan benang, dll.
Saiz kolam benang: Saiz kolam benang perlu ditentukan berdasarkan keperluan khusus aplikasi. Jika aplikasi perlu mengendalikan sejumlah besar tugas jangka pendek, anda boleh menetapkan saiz kumpulan benang yang lebih kecil jika aplikasi perlu mengendalikan tugasan intensif secara pengiraan, anda boleh menetapkan saiz kumpulan benang yang lebih besar.
Jenis baris gilir tugas: Jenis baris gilir tugas juga perlu ditentukan berdasarkan keperluan khusus aplikasi. Jika bilangan tugasan adalah besar, tetapi masa pelaksanaan setiap tugasan adalah pendek, baris gilir tidak terhad boleh digunakan jika bilangan tugas adalah kecil, tetapi masa pelaksanaan setiap tugasan adalah panjang, baris gilir terhad boleh digunakan.
Pengendalian pengecualian kumpulan benang: Tugasan dalam kumpulan benang mungkin membuang pengecualian, dan pengendalian pengecualian yang sesuai diperlukan untuk mengelakkan tugas lain dalam kumpulan benang daripada terjejas. Anda boleh menggunakan blok cuba-tangkap untuk menangkap pengecualian yang dilemparkan oleh tugasan dan mengendalikannya dengan sewajarnya, seperti pengelogan, penyerahan semula tugas, dsb.
Pemantauan kumpulan benang: Pemantauan kumpulan benang boleh membantu kami memahami status dan prestasi kumpulan benang untuk penalaan yang sesuai. Anda boleh menggunakan JMX (Sambungan Pengurusan Java) atau komponen pemantauan tersuai untuk memantau status larian kumpulan utas, seperti bilangan utas aktif dalam kumpulan utas, bilangan tugas dalam baris gilir tugas, bilangan tugasan selesai, dll.
Di bawah, kami akan menggunakan contoh untuk menunjukkan cara menggunakan kumpulan benang untuk mengoptimumkan prestasi aplikasi .
Contoh: Mengira Jujukan Fibonacci
Kami akan menunjukkan cara menggunakan kumpulan benang untuk mengira Jujukan Fibonacci melalui contoh mudah untuk menunjukkan cara kumpulan benang boleh meningkatkan prestasi aplikasi. prestasi.
Jujukan Fibonacci ialah jujukan yang ditakrifkan secara rekursif, ditakrifkan seperti berikut:
F(0) = 0
F (1) = 1
F(n) = F(n-1) + F(n-2), n > 1
Kita boleh menggunakan algoritma rekursif untuk mengira jujukan Fibonacci, tetapi algoritma rekursif kurang cekap kerana ia akan berulang kali mengira beberapa nilai. Sebagai contoh, pengiraan F(5) memerlukan pengiraan F(4) dan F(3), pengiraan F(4) memerlukan pengiraan F(3) dan F(2), dan pengiraan F(3) memerlukan pengiraan F(2) dan F(2) F(1), dapat dilihat bahawa F(3) dan F(2) dikira dua kali.
Kami boleh menggunakan kumpulan benang untuk mengelakkan pengiraan berulang dan dengan itu meningkatkan prestasi aplikasi. Langkah-langkah pelaksanaan khusus adalah seperti berikut:
Pisah tugas kepada berbilang subtugas dan setiap subtugas mengira nilai jujukan Fibonacci.
Serahkan subtugasan ke kumpulan benang untuk pelaksanaan serentak.
Gunakan ConcurrentHashMap untuk cache nilai yang telah dikira untuk mengelakkan pengiraan berulang.
Tunggu sehingga semua tugasan selesai dan pulangkan hasilnya.
Berikut ialah kod pelaksanaan:
import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask; public class FibonacciTask extends RecursiveTask<Integer> { private static final long serialVersionUID = 1L; private static final Map<Integer, Integer> cache = new ConcurrentHashMap<>(); private final int n; public FibonacciTask(int n) { this.n = n; } @Override protected Integer compute() { if (n == 0) { return 0; } if (n == 1) { return 1; } Integer result = cache.get(n); if (result != null) { return result; } FibonacciTask f1 = new FibonacciTask(n - 1); FibonacciTask f2 = new FibonacciTask(n - 2); f1.fork(); f2.fork(); result = f1.join() + f2.join(); cache.put(n, result); return result; } public static void main(String[] args) throws ExecutionException, InterruptedException { ForkJoinPool pool = new ForkJoinPool(); FibonacciTask task = new FibonacciTask(10); System.out.println(pool.invoke(task)); } }
Dalam kod di atas, kami menggunakan ForkJoinPool sebagai kumpulan benang dan setiap subtugas mengira Nilai jujukan Fibonacci, gunakan ConcurrentHashMap ke cache nilai yang telah dikira untuk mengelakkan pengiraan berulang. Akhir sekali, tunggu semua tugasan selesai dan kembalikan hasilnya.
Kita dapat melihat bahawa dalam contoh di atas, kita menggunakan ForkJoinPool sebagai kumpulan benang dan mewarisi kelas RecursiveTask untuk melaksanakan pengiraan serentak jujukan Fibonacci. Dalam kaedah pengiraan(), kami mula-mula menyemak sama ada nilai jujukan Fibonacci telah dikira dalam cache Jika ia telah dikira, keputusan dalam cache dikembalikan secara langsung. Jika tidak, kami mencipta dua subtugas f1 dan f2, menyerahkannya ke kumpulan benang untuk pelaksanaan serentak, menggunakan kaedah join() untuk menunggu keputusan pelaksanaannya dan menambah hasil pelaksanaannya sebagai hasil pelaksanaan tugas semasa, dan pada pada masa yang sama tambahkan ini Nilai-nilai jujukan Bonacci dan keputusan pengiraannya disimpan dalam cache supaya keputusan boleh diperolehi terus dari cache pada kali pengiraan seterusnya dilakukan.
Dalam kaedah main(), kami mencipta objek ForkJoinPool dan mencipta objek FibonacciTask, kemudian memanggil kaedah invoke() untuk melaksanakan tugas dan mencetak hasil pelaksanaan ke konsol.
Melalui contoh mudah ini, kita dapat melihat bahawa menggunakan kumpulan benang boleh meningkatkan prestasi aplikasi, terutamanya dalam tugasan intensif pengiraan. Kumpulan benang boleh melaksanakan tugas secara serentak, dengan itu menggunakan sepenuhnya kuasa pengkomputeran CPU berbilang teras, mengelakkan penciptaan dan pemusnahan benang yang kerap, dengan itu mengurangkan kos penukaran konteks benang dan meningkatkan prestasi aplikasi dan kebolehskalaan.
Atas ialah kandungan terperinci Cara menggunakan kumpulan benang Java untuk mengoptimumkan aplikasi kami. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!