Kata pengantar
Dalam pemrograman multi-threaded, tidak realistis untuk menetapkan utas untuk setiap tugas, dan konsumsi overhead dan sumber daya pembuatan utas sangat tinggi. Kolam utas muncul dan menjadi alat yang ampuh bagi kami untuk mengelola utas. Melalui antarmuka pelaksana, Java menyediakan metode standar untuk memisahkan proses pengiriman tugas dan menjalankan proses, dan menggunakan Runnable untuk mewakili tugas.
Selanjutnya, mari kita analisis implementasi Java Thread Pool Framework ThreadPoolExecutor.
Analisis berikut didasarkan pada JDK1.7
siklus hidup
Di ThreadPoolExecutor , kapasitas 3 bit atas digunakan untuk mewakili keadaan berjalan, yaitu:
1.Running: Terima tugas baru dan proses tugas dalam antrian tugas
2.Shutdown: Tugas yang tidak menerima tugas baru tetapi menangani antrian tugas
3. Stop: Tidak ada tugas baru yang diterima, tidak ada antrian tugas yang dirilis, dan semua tugas yang sedang berlangsung terganggu pada saat yang sama
4.Tidying: Semua tugas telah diakhiri, jumlah utas pekerja adalah 0. Ketika keadaan ini tercapai, diakhiri () akan dieksekusi.
5. Diakhiri: Terakhir () telah dieksekusi
Diagram transisi negara
Kelas atom digunakan untuk mewakili bit negara bagian di ThreadPoolExecutor
Private Final AtomicInteger CTL = AtomicInteger baru (CTLOF (Running, 0));
Model kumpulan benang
Parameter inti
CorePoolsize: Jumlah minimum utas pekerja hidup (jika AllowCorethreadTimeOut diatur, maka nilai ini 0)
MaximumpoolSize: Jumlah maksimum utas, dibatasi berdasarkan kapasitas
Keepalivetime: Waktu kelangsungan hidup utas yang sesuai, unit waktu ditentukan oleh TimeUnit
WorkQueue: antrian kerja, menyimpan tugas yang akan dieksekusi
RIMETEXECUTECECUTHANDLER: Tolak Kebijakan, kapasitas maksimum kumpulan utas akan dipicu setelah kumpulan utas penuh: kapasitas tiga bit pertama digunakan sebagai bit bendera, yaitu kapasitas maksimum utas pekerja adalah (2^29) -1
Empat model
CachedThreadpool: Kolam benang yang bisa di -cache. Jika ukuran kumpulan utas saat ini melebihi persyaratan pemrosesan, utas idle akan didaur ulang. Ketika permintaan meningkat, utas baru dapat ditambahkan. Tidak ada batasan ukuran kumpulan benang.
FixedThreadPool: Kumpulan utas ukuran tetap. Saat mengirimkan tugas, utas dibuat sampai jumlah maksimum kumpulan utas tercapai. Pada saat ini, ukuran kumpulan utas tidak akan lagi berubah.
Singlethreadpool: Seekor kumpulan utas utas tunggal, yang hanya memiliki satu utas pekerja untuk menjalankan tugas. Ini dapat memastikan bahwa tugas dieksekusi secara serial dalam urutan di mana mereka berada dalam antrian. Jika utas ini berakhir secara tidak normal, utas baru akan dibuat untuk menjalankan tugas.
TerjadwalThreadPool: Kumpulan utas ukuran tetap dan melakukan tugas dengan cara yang tertunda atau waktunya, mirip dengan timer.
Jalankan eksekusi tugas
Logika inti:
1. Jumlah utas saat ini <corepoolsize, langsung buka utas inti baru untuk menjalankan tugas addworker (perintah, true)
2. Jumlah utas saat ini> = corePoolsize, dan tugas berhasil ditambahkan ke antrian kerja
1). Periksa apakah keadaan kumpulan utas saat ini sedang berjalan
2). Jika tidak, tugas itu ditolak
3). Jika demikian, tentukan apakah jumlah utas saat ini adalah 0. Jika 0, tambahkan utas pekerja.
3. Nyalakan tugas eksekusi utas normal addworker (perintah, false), dan tolak tugas jika gagal untuk memulai. Dari analisis di atas, kita dapat meringkas empat tahap operasi kumpulan benang:
1) .Poolsize <corePoolsize dan antriannya kosong. Utas baru akan dibuat untuk memproses tugas yang dikirimkan.
2) .poolsize == corePoolsize. Pada saat ini, tugas yang diajukan memasuki antrian kerja. Utas pekerja memperoleh eksekusi tugas dari antrian. Pada saat ini, antriannya tidak kosong dan tidak penuh.
3) .poolsize == corePoolsize dan antriannya penuh. Utas baru juga akan dibuat untuk memproses tugas yang dikirimkan, tetapi poolSize <maxpoolsize
4) .poolsize == maxpoolsize dan antriannya penuh, kebijakan penolakan akan dipicu
Kebijakan Penolakan <BR /> Kami menyebutkan sebelumnya bahwa jika suatu tugas tidak dapat dieksekusi, itu akan ditolak. Ditolak ExecutionHandler adalah antarmuka untuk menangani tugas yang ditolak. Berikut adalah empat strategi penolakan.
Abortpolicy: Kebijakan Default, Akhiri Tugas, Lempar Tolak Exception
CallerRunSpolicy: Jalankan tugas saat ini di utas penelepon tanpa melempar pengecualian
Discardpolicy: Buang kebijakan, langsung buang tugas, dan jangan melempar pengecualian
Di skandolderspolicy: Abaikan tugas tertua, jalankan tugas saat ini, dan jangan melemparkan pengecualian
Pekerja di kumpulan utas
Pekerja mewarisi AbstractQueuedsynchronizer dan Runnable. Yang pertama memberi pekerja fungsi kunci, dan yang terakhir mengeksekusi metode utama runworker utas pekerja (pekerja w) (eksekusi tugas snap dari antrian tugas). Referensi pekerja ditemukan dalam koleksi pekerja dan dilindungi oleh Mainlock.
Private Final Reentrantlock Mainlock = baru reentrantlock ();
hashset final pribadi <worker> pekerja = hashset baru <worker> ();
Fungsi Inti Runworker
Berikut ini adalah logika yang disederhanakan, Catatan: Jalankan masing -masing utas pekerja menjalankan fungsi berikut
final void runworker (pekerja w) {thread wt = thread.currentThread (); Runnable Task = W.FirstTask; w.firsttask = null; while (tugas! = null || (tugas = getTask ())! = null) {w.lock (); beforeexecute (wt, tugas); task.run (); afterexecute (tugas, dilemparkan); w.unlock (); } ProcessWorkerExit (w, selesai lebih);} 1. Dapatkan tugas dari gettask ()
2. Kunci Pekerja
3. Execute beforeexecute (wt, tugas), yang merupakan metode ekstensi yang disediakan oleh threadpoolexecutor ke subkelas
4. Jalankan tugas. Jika pekerja telah mengonfigurasi tugas pertama, tugas pertama akan dieksekusi terlebih dahulu dan hanya sekali.
5. Eksekusi afterexecute (tugas, dilemparkan);
6. Buka kunci pekerja
7. Jika tugas yang diperoleh adalah nol, tutup pekerja
Dapatkan tugas gettask
Antrian tugas di dalam kumpulan utas adalah antrian pemblokiran, yang dilewatkan selama konstruksi.
workqueue blockingqueue akhir pribadi <Runnable>;
gettask () mendapatkan tugas dari antrian tugas, mendukung pemblokiran dan waktu tunggu menunggu tugas. Empat situasi akan menyebabkan NULL dikembalikan dan pekerja ditutup.
1. Jumlah utas yang ada melebihi jumlah maksimum utas
2. Kolam utas dalam keadaan berhenti
3. Kolam utas dalam keadaan shutdown dan antrian kerja kosong
4. Thread menunggu batas waktu, dan jumlah utas melebihi jumlah utas yang disimpan
Logika inti: Tak terjadilah atau memblokir tugas menunggu pada antrian pemblokiran. Tugas menunggu waktunya akan menyebabkan utas pekerja ditutup.
Timed = AllowCorethreadTimeout || WC> corePoolsize; runnable r = waktunya? workqueue.poll (Keepalivetime, timeunit.nanoseconds): workqueue.take ();
Menunggu tugas akan habis dalam dua kasus:
1. Izinkan utas inti untuk menunggu batas waktu, yaitu, izinCorethreadTimeOut (true)
2. Utas saat ini adalah utas normal, saat ini wc> corePoolsize
Antrian kerja menggunakan blockingqueue, jadi saya tidak akan memperluasnya di sini. Saya akan menulis analisis terperinci nanti.
Meringkaskan
ThreadPoolExecutor didasarkan pada model produser-konsumen. Pengoperasian tugas mengirimkan setara dengan produsen, dan utas tugas pelaksanaan setara dengan konsumen.
Executors menyediakan empat metode untuk membangun model kumpulan utas berdasarkan ThreadPoolExecutor. Selain itu, kami dapat secara langsung mewarisi threadPoolExecutor dan menulis ulang metode beforeexecute dan afterexecute untuk menyesuaikan proses eksekusi tugas kumpulan utas.
Menggunakan antrian yang dibatasi atau antrian yang tidak terikat perlu dipertimbangkan sesuai dengan situasi tertentu, dan ukuran antrian kerja dan jumlah utas juga perlu dipertimbangkan dengan cermat.
Kebijakan penolakan disarankan untuk menggunakan Callerrunspolicy, yang tidak meninggalkan tugas atau melempar pengecualian, tetapi malah jatuh kembali tugas ke utas penelepon untuk dieksekusi.
Di atas adalah semua konten artikel ini. Saya harap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.