Rumah  >  Artikel  >  Kumpulan benang Python dan prinsip dan kegunaannya

Kumpulan benang Python dan prinsip dan kegunaannya

zbt
zbtasal
2023-06-20 16:44:251591semak imbas

Kos sistem memulakan rangkaian baharu agak tinggi kerana ia melibatkan interaksi dengan sistem pengendalian. Dalam kes ini, menggunakan kumpulan benang boleh meningkatkan prestasi, terutamanya apabila program perlu mencipta sejumlah besar benang dengan jangka hayat yang singkat, anda harus mempertimbangkan untuk menggunakan kumpulan benang. Kumpulan benang mencipta sejumlah besar benang melahu apabila sistem bermula Selagi program menyerahkan fungsi kepada kumpulan benang, kumpulan benang akan memulakan benang melahu untuk melaksanakannya. Apabila fungsi dilaksanakan, benang tidak akan mati, tetapi akan kembali ke kolam benang sekali lagi dan menjadi melahu menunggu untuk melaksanakan fungsi seterusnya.

Kumpulan benang Python dan prinsip dan kegunaannya

Kos sistem memulakan rangkaian baharu agak tinggi kerana ia melibatkan interaksi dengan sistem pengendalian. Dalam kes ini, menggunakan kumpulan benang boleh meningkatkan prestasi, terutamanya apabila program perlu mencipta sejumlah besar benang dengan jangka hayat yang singkat, anda harus mempertimbangkan untuk menggunakan kumpulan benang.

Kumpulan benang menghasilkan sejumlah besar benang melahu apabila sistem dimulakan selagi program menyerahkan fungsi kepada kumpulan benang, kumpulan benang akan memulakan benang melahu untuk melaksanakannya. Apabila pelaksanaan fungsi tamat, benang tidak akan mati, tetapi akan kembali ke kolam benang sekali lagi dan menjadi melahu, menunggu pelaksanaan fungsi seterusnya.

Selain itu, menggunakan kumpulan benang boleh mengawal bilangan benang serentak dalam sistem dengan berkesan. Apabila sistem mengandungi sejumlah besar utas serentak, ia akan menyebabkan penurunan mendadak dalam prestasi sistem dan juga menyebabkan Python gagal. Jurubahasa ranap, dan bilangan maksimum parameter utas kumpulan benang boleh mengawal bilangan utas serentak dalam sistem untuk tidak melebihi bilangan ini.

Penggunaan kumpulan benang

Kelas asas kumpulan benang ialah Pelaksana dalam modul concurrent.futures menyediakan dua subkelas, iaitu ThreadPoolExecutor dan ProcessPoolExecutor, di mana ThreadPoolExecutor digunakan untuk mencipta kumpulan benang dan ProcessPoolExecutor digunakan untuk mencipta kumpulan proses.

Jika anda menggunakan kumpulan benang/kumpulan proses untuk mengurus pengaturcaraan serentak, maka anda hanya perlu menyerahkan fungsi tugasan yang sepadan kepada kumpulan benang/kumpulan proses dan kumpulan benang/kumpulan proses akan menguruskan berehat.

Exectuor menyediakan kaedah biasa berikut:

serahkan(fn, *args, **kwargs): Serahkan fungsi fn ke kumpulan benang. *args mewakili parameter yang dihantar ke fungsi fn, *kwargs Menunjukkan bahawa parameter dihantar ke fungsi fn dalam bentuk argumen kata kunci.

map(func, *iterables, timeout=None, chunksize=1): Fungsi ini serupa dengan peta fungsi global(func, *iterables), tetapi fungsi ini akan memulakan berbilang benang untuk segera melaksanakan pemprosesan peta pada iterables secara tidak segerak.

tutup(tunggu=Benar): Tutup kumpulan benang.

Selepas program menyerahkan fungsi tugasan ke kumpulan benang, kaedah hantar akan mengembalikan objek Masa Depan Kelas digunakan terutamanya untuk mendapatkan nilai pulangan fungsi tugas benang. Memandangkan tugas utas akan dilaksanakan secara tidak segerak dalam utas baharu, fungsi yang dilaksanakan oleh utas adalah bersamaan dengan tugas "penyiapan masa hadapan", jadi Python menggunakan Masa depan untuk mewakili.

Malah, terdapat juga Masa Depan dalam pengaturcaraan berbilang benang Java di sini adalah serupa dengan Masa Depan Java.

Future menyediakan kaedah berikut:

cancel(): Batalkan tugas thread yang diwakili oleh Future ini. Jika tugas sedang dilaksanakan dan tidak boleh dibatalkan, kaedah mengembalikan Palsu jika tidak, program membatalkan tugas dan kembali betul.

cancelled(): Mengembalikan sama ada tugas urutan yang diwakili oleh Future berjaya dibatalkan.

running(): Jika tugas utas yang diwakili oleh Masa Depan sedang dilaksanakan dan tidak boleh dibatalkan, kaedah ini mengembalikan True.

done(): Jika tugasan urutan yang diwakili oleh Funture ini berjaya dibatalkan atau diselesaikan, kaedah ini mengembalikan True.

result(timeout=None): Dapatkan hasil terakhir yang dikembalikan oleh tugasan urutan yang diwakili oleh Masa Depan ini. Jika Masa Depan Jika tugasan benang yang diwakili belum selesai, kaedah ini akan menyekat benang semasa, di mana parameter tamat masa menentukan bilangan saat maksimum untuk disekat.

exception(timeout=None): Dapatkan pengecualian yang disebabkan oleh tugas urutan yang diwakili oleh Masa Depan ini. Jika tugas selesai dengan jayanya tanpa pengecualian, kaedah itu kembali tiada.

add_done_callback(fn): Daftarkan "fungsi panggil balik" untuk tugasan urutan yang diwakili oleh Masa Depan ini Apabila tugasan berjaya diselesaikan, program akan mencetuskan fn secara automatik fungsi.

Selepas menggunakan kumpulan benang, kaedah penutupan() kumpulan benang hendaklah dipanggil, yang akan memulakan urutan penutupan kumpulan benang. penutupan panggilan() Kumpulan benang selepas kaedah tidak lagi akan menerima tugasan baharu, tetapi akan menyelesaikan semua tugasan yang diserahkan sebelum ini. Apabila semua tugas dalam kumpulan benang telah dilaksanakan, semua benang dalam kumpulan benang akan mati.

Langkah-langkah untuk menggunakan kumpulan benang untuk melaksanakan tugasan benang adalah seperti berikut:

Panggil pembina kelas ThreadPoolExecutor untuk mencipta kumpulan benang.

Tentukan fungsi biasa sebagai tugasan benang.

Panggil kaedah submit() objek ThreadPoolExecutor untuk menyerahkan tugasan thread.

Apabila anda tidak mahu menyerahkan sebarang tugas, panggil kaedah shutdown() objek ThreadPoolExecutor untuk menutup kumpulan benang.

Atur cara berikut menunjukkan cara menggunakan kumpulan benang untuk melaksanakan tugasan benang:

from concurrent.futures import ThreadPoolExecutor
import threading
import time
# 定义一个准备作为线程任务的函数
def action(max):
my_sum = 0
for i in range(max):
print(threading.current_thread().name + ' ' + str(i))
my_sum += i
return my_sum
# 创建一个包含2条线程的线程池
pool = ThreadPoolExecutor(max_workers=2)
# 向线程池提交一个task, 50会作为action()函数的参数
future1 = pool.submit(action, 50)
# 向线程池再提交一个task, 100会作为action()函数的参数
future2 = pool.submit(action, 100)
# 判断future1代表的任务是否结束
print(future1.done())
time.sleep(3)
# 判断future2代表的任务是否结束
print(future2.done())
# 查看future1代表的任务返回的结果
print(future1.result())
# 查看future2代表的任务返回的结果
print(future2.result())
# 关闭线程池
pool.shutdown()

Dalam atur cara di atas, baris ke-13 kod mencipta kumpulan utas yang mengandungi dua utas Dalam dua baris kod seterusnya, cuma tambahkan tindakan() Fungsi diserahkan kepada kumpulan benang, dan kumpulan benang bertanggungjawab untuk memulakan benang untuk melaksanakan fungsi action(). Kaedah memulakan benang ini adalah elegan dan lebih cekap.

Apabila atur cara menyerahkan fungsi action() ke kumpulan benang, kaedah submit() akan mengembalikan objek Masa Depan yang sepadan dengan tugasan dan atur cara segera menentukan futurel done() kaedah, yang akan mengembalikan False (menunjukkan bahawa tugas itu belum selesai pada masa ini). Seterusnya, program utama berhenti seketika selama 3 saat, dan kemudian menentukan done() masa hadapan2 kaedah, jika tugasan telah selesai pada masa ini, maka kaedah ini akan mengembalikan Benar.

Program akhirnya memperoleh hasil yang dikembalikan oleh dua tugas tak segerak melalui kaedah result() Future.

Pembaca boleh menjalankan kod ini sendiri untuk melihat hasilnya, yang tidak akan ditunjukkan di sini.

Apabila program menggunakan kaedah Future's result() untuk mendapatkan hasilnya, kaedah ini akan menyekat urutan semasa jika tamat masa tidak ditentukan. parameter, urutan semasa akan kekal disekat sehingga tugas yang diwakili oleh Masa Depan kembali.

Dapatkan hasil pelaksanaan

Atur cara sebelumnya yang dipanggil result() kaedah Masa Depan untuk mendapatkan nilai pulangan tugas utas, tetapi kaedah ini akan menyekat utas utama semasa dan hanya akan menunggu sehingga tugas proses wang selesai , result() Penyekatan kaedah akan dikeluarkan.

Jika program tidak mahu memanggil terus kaedah result() untuk menyekat urutan, ia boleh menggunakan add_done_callback() Future's Kaedah untuk menambah fungsi panggil balik, fungsi panggil balik kelihatan seperti fn(masa hadapan). Apabila tugas benang selesai, program akan mencetuskan fungsi panggil balik secara automatik dan memindahkan Masa Depan yang sepadan Objek diluluskan sebagai parameter kepada fungsi panggil balik.

Atur cara berikut menggunakan kaedah add_done_callback() untuk mendapatkan nilai pulangan tugas benang:

from concurrent.futures import ThreadPoolExecutor
import threading
import time
# 定义一个准备作为线程任务的函数
def action(max):
my_sum = 0
for i in range(max):
print(threading.current_thread().name + ' ' + str(i))
my_sum += i
return my_sum
# 创建一个包含2条线程的线程池
with ThreadPoolExecutor(max_workers=2) as pool:
# 向线程池提交一个task, 50会作为action()函数的参数
future1 = pool.submit(action, 50)
# 向线程池再提交一个task, 100会作为action()函数的参数
future2 = pool.submit(action, 100)
def get_result(future):
print(future.result())
# 为future1添加线程完成的回调函数
future1.add_done_callback(get_result)
# 为future2添加线程完成的回调函数
future2.add_done_callback(get_result)
print('--------------')

Atur cara utama di atas menambah fungsi panggil balik yang sama untuk future1 dan future2 masing-masing dan panggilan balik fungsi akan digunakan dalam tugasan benang Dapatkan nilai pulangannya apabila selesai.

Barisan terakhir kod dalam program utama mencetak garis mendatar. Kerana program ini tidak secara langsung memanggil result() future1 dan future2 kaedah, jadi benang utama tidak akan disekat dan anda boleh segera melihat garisan mendatar yang dicetak oleh benang utama output. Seterusnya, anda akan melihat dua utas baharu dilaksanakan secara serentak Apabila tugasan utas selesai, get_result() Fungsi ini dicetuskan dan mengeluarkan nilai pulangan tugas benang.

Selain itu, memandangkan kumpulan benang melaksanakan Protokol Urus Konteks, atur cara ini boleh digunakan dengan kenyataan untuk menguruskan kumpulan benang, dengan itu mengelakkan keperluan untuk menutup kumpulan benang secara manual, seperti yang ditunjukkan dalam program di atas.

Selain itu, Exectuor juga menyediakan peta(func, *iterables, timeout=None, chunksize=1) Kaedah. Fungsi kaedah ini adalah serupa dengan fungsi global map(). fungsi. Kaedah ini bersamaan dengan memulakan benang len(iterables) dan mengumpul hasil pelaksanaan setiap utas.

Sebagai contoh, atur cara berikut menggunakan kaedah map() Pelaksana untuk memulakan utas dan mengumpul nilai pulangan tugas utas:

from concurrent.futures import ThreadPoolExecutor
import threading
import time
# 定义一个准备作为线程任务的函数
def action(max):
my_sum = 0
for i in range(max):
print(threading.current_thread().name + ' ' + str(i))
my_sum += i
return my_sum
# 创建一个包含4条线程的线程池
with ThreadPoolExecutor(max_workers=4) as pool:
# 使用线程执行map计算
# 后面元组有3个元素,因此程序启动3条线程来执行action函数
results = pool.map(action, (50, 100, 150))
print('--------------')
for r in results:
print(r)

Atur cara di atas menggunakan kaedah map() untuk mulakan 3 utas (kumpulan utas program mengandungi 4 Jika anda terus menggunakan kumpulan benang yang mengandungi hanya dua utas, satu tugasan akan berada dalam keadaan menunggu pada masa ini. , peta() Nilai pulangan kaedah akan mengumpulkan hasil pulangan setiap tugasan benang.

Jalankan program di atas, anda juga boleh melihat hasil pelaksanaan serentak 3 utas Akhirnya, anda boleh melihat hasil pengembalian 3 tugasan utas melalui keputusan.

Seperti yang dapat dilihat daripada atur cara di atas, menggunakan kaedah map() untuk memulakan thread dan mengumpul hasil pelaksanaan thread bukan sahaja mempunyai kelebihan kod mudah, tetapi juga walaupun program akan melaksanakan tindakan () serentak fungsi, tetapi hasil pelaksanaan fungsi action() yang dikumpul pada penghujung masih konsisten dengan hasil parameter yang diluluskan. Iaitu, elemen pertama keputusan di atas ialah tindakan(50) Elemen kedua ialah hasil tindakan(100), dan elemen ketiga ialah hasil tindakan(150).

Atas ialah kandungan terperinci Kumpulan benang Python dan prinsip dan kegunaannya. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel sebelumnya:Apakah maksud perangkak web?Artikel seterusnya:Apakah maksud perangkak web?