Rumah > Artikel > pembangunan bahagian belakang > Python berbilang benang dan susunan terperinci berbilang proses
Proses dan benang ialah konsep asas sistem pengendalian, tetapi ia agak abstrak dan sukar untuk difahami. Mengenai berbilang proses dan berbilang benang, ayat paling klasik dalam buku teks ialah "Proses ialah unit terkecil peruntukan sumber dan benang ialah unit terkecil penjadualan CPU." Benang ialah satu aliran kawalan berurutan dalam program. Unit pelaksanaan yang agak bebas dan boleh dijadualkan dalam proses Ia adalah unit asas untuk sistem menjadualkan dan memperuntukkan CPU secara bebas. Ia merujuk kepada unit penjadualan program yang sedang berjalan. Menjalankan berbilang benang pada masa yang sama untuk menyelesaikan tugas yang berbeza dalam satu program dipanggil multithreading.
Proses ialah unit asas peruntukan sumber. Semua sumber yang berkaitan dengan proses direkodkan dalam blok kawalan proses PCB. Untuk menunjukkan bahawa proses memiliki sumber ini atau sedang menggunakannya. Di samping itu, proses itu juga merupakan unit penjadualan yang mendahului pemproses, dan ia mempunyai ruang alamat maya yang lengkap. Apabila proses dijadualkan, proses yang berbeza mempunyai ruang alamat maya yang berbeza, dan urutan yang berbeza dalam proses yang sama berkongsi ruang alamat yang sama.
Bersesuaian dengan proses, utas tidak ada kaitan dengan peruntukan sumber Ia tergolong dalam proses tertentu dan berkongsi sumber proses dengan utas lain dalam proses tersebut. Benang hanya terdiri daripada daftar tindanan (tindanan sistem atau tindanan pengguna) yang berkaitan dan jadual kawalan benang TCB. Daftar boleh digunakan untuk menyimpan pembolehubah tempatan dalam utas, tetapi tidak boleh menyimpan pembolehubah yang berkaitan dengan utas lain.
Biasanya proses boleh mengandungi beberapa utas, yang boleh menggunakan sumber yang dimiliki oleh proses tersebut. Dalam sistem pengendalian yang memperkenalkan benang, proses biasanya dianggap sebagai unit asas peruntukan sumber, dan benang dianggap sebagai unit asas operasi bebas dan penjadualan bebas.
Memandangkan urutan lebih kecil daripada proses dan pada asasnya tidak memiliki sumber sistem, overhed penjadualannya akan menjadi lebih kecil, yang boleh meningkatkan tahap pelaksanaan serentak berbilang program dalam sistem dengan lebih cekap menambah baik penggunaan sumber sistem dan pemprosesan.
Oleh itu, sistem pengendalian tujuan umum yang dilancarkan dalam beberapa tahun kebelakangan ini telah memperkenalkan urutan untuk menambah baik keselarasan sistem, dan menganggapnya sebagai penunjuk penting sistem pengendalian moden.
Perbezaan antara urutan dan proses boleh diringkaskan sebagai empat perkara berikut:
Dimensi kontras |
Berbilang proses |
Berbilang- benang |
Ringkasan |
Perkongsian dan penyegerakan data |
Perkongsian data adalah rumit, penyegerakan adalah mudah |
Perkongsian data adalah mudah, penyegerakan adalah rumit |
Setiap mempunyai kebaikan dan keburukan tersendiri |
Memori, CPU |
Mengambil banyak memori, penukaran rumit, rendah Penggunaan CPU |
Menduduki kurang memori, penukaran mudah, penggunaan CPU yang tinggi |
Dikuasai benang |
Buat , musnahkan, tukar |
Kompleks, perlahan |
Mudah, cepat |
Thread diduduki Cemerlang |
Pengaturcaraan dan penyahpepijatan |
Pengaturcaraan yang mudah dan penyahpepijatan yang mudah |
Pengaturcaraan yang rumit, penyahpepijatan yang rumit |
Proses dominan |
Kebolehpercayaan |
Proses tidak akan menjejaskan satu sama lain |
Jika satu utas ditutup, keseluruhan proses akan ditutup |
Proses mengambil kesempatan |
Diedarkan |
Sesuai untuk multi-core dan multi-machine, mudah dikembangkan ke beberapa mesin |
Sesuai untuk multi- teras | Penguasaan Proses |
Untuk meringkaskan, proses dan benang juga boleh dibandingkan dengan kereta api dan gerabak:
Kunci Jurubahasa Global (Bahasa Inggeris: Global Interpreter Lock, GIL (disingkat GIL) bukanlah ciri Python, ia adalah konsep yang diperkenalkan semasa melaksanakan penghurai Python (CPython). Kerana CPython ialah persekitaran pelaksanaan Python lalai dalam kebanyakan persekitaran. Oleh itu, dalam konsep ramai orang, CPython ialah Python, dan mereka mengambil mudah bahawa GIL adalah kecacatan bahasa Python. Jadi apakah GIL dalam pelaksanaan CPython? Mari kita lihat penjelasan rasmi:
Mekanisme yang digunakan oleh penterjemah CPython untuk memastikan bahawa hanya satu utas melaksanakan kod bait Python pada satu masa Ini memudahkan pelaksanaan CPython dengan membuat model objek (termasuk terbina kritikal. dalam jenis seperti dict) secara tersirat selamat terhadap akses serentak Mengunci keseluruhan penterjemah memudahkan jurubahasa untuk berbilang benang, dengan mengorbankan banyak keselarian yang diberikan oleh mesin berbilang pemproses.
Python. Pelaksanaan kod dikawal oleh mesin maya Python (juga dipanggil gelung utama penterjemah, versi CPython pada asalnya direka untuk hanya mempunyai satu utas yang dilaksanakan dalam gelung utama jurubahasa pada masa yang sama, iaitu, pada bila-bila masa, hanya satu). benang Benang berjalan dalam penterjemah. Akses kepada mesin maya Python dikawal oleh Global Interpreter Lock (GIL), yang memastikan bahawa hanya satu utas berjalan pada satu masa.
Apakah kebaikan GIL? Ringkasnya, ia lebih pantas dalam situasi satu-benang dan lebih mudah apabila digabungkan dengan perpustakaan C, dan tidak perlu mempertimbangkan isu keselamatan benang Ini juga merupakan senario aplikasi yang paling biasa dan kelebihan Python awal. Di samping itu, reka bentuk GIL memudahkan pelaksanaan CPython, menjadikan model objek, termasuk jenis terbina dalam utama seperti kamus, boleh diakses secara tersirat secara serentak. Mengunci penterjemah global menjadikannya lebih mudah untuk melaksanakan sokongan berbilang benang, tetapi ia juga kehilangan keupayaan pengkomputeran selari hos berbilang pemproses.
Dalam persekitaran berbilang benang, mesin maya Python melaksanakan seperti berikut:
Sebelum Python3.2, logik keluaran GIL ialah benang semasa menghadapi operasi IO atau kiraan kutu mencapai 100 (kutu boleh dianggap sebagai ular sawa itu sendiri Pembilang, digunakan khas untuk GIL, yang ditetapkan semula kepada sifar selepas setiap keluaran. Kiraan ini boleh dilaraskan melalui sys.setcheckinterval) sebelum dikeluarkan. Kerana benang intensif pengkomputeran akan segera memohon untuk GIL selepas melepaskan GIL, dan biasanya ia telah memperoleh semula GIL sebelum benang lain selesai menjadualkan Ini akan menyebabkan benang intensif pengkomputeran memperoleh GIL dalam masa yang sangat singkat GIL akan diduduki untuk masa yang lama, walaupun sehingga pelaksanaan thread berakhir.
Python 3.2 mula menggunakan GIL baharu. Pelaksanaan GIL baharu menggunakan tamat masa tetap untuk mengarahkan utas semasa untuk melepaskan kunci global. Apabila benang semasa memegang kunci ini dan benang lain meminta kunci ini, benang semasa akan dipaksa untuk melepaskan kunci selepas 5 milisaat. Penambahbaikan ini memperbaiki keadaan di mana satu benang menduduki GIL untuk masa yang lama dalam kes teras tunggal.
Pada CPU teras tunggal, beratus semakan selang akan menghasilkan suis benang. Pada CPU berbilang teras, terdapat hentakan benang yang teruk. Setiap kali kunci GIL dilepaskan, benang bersaing untuk mengunci dan menukar benang, yang menggunakan sumber. Dengan berbilang benang di bawah satu teras, setiap kali GIL dilepaskan, benang yang dibangkitkan boleh mendapatkan kunci GIL, jadi ia boleh dilaksanakan dengan lancar Walau bagaimanapun, di bawah berbilang teras, selepas CPU0 mengeluarkan GIL, benang pada CPU lain akan bersaing. tetapi GIL boleh Ia diperolehi dengan serta-merta oleh CPU0, menyebabkan benang yang dibangkitkan pada beberapa CPU lain bangun dan menunggu masa penukaran sebelum memasuki keadaan yang akan dijadualkan Ini akan menyebabkan benang meronta, mengakibatkan kecekapan yang lebih rendah.
Selain itu, daripada mekanisme pelaksanaan di atas, dapat disimpulkan bahawa multi-threading Python lebih mesra kepada kod intensif IO daripada kod intensif CPU.
Langkah balas terhadap GIL:
Python's threading package terutamanya menggunakan pembangunan multi-threading, tetapi disebabkan kewujudan GIL, banyak Threads tidak sebenarnya berbilang benang Jika anda ingin menggunakan sepenuhnya sumber CPU berbilang teras, anda perlu menggunakan berbilang proses dalam kebanyakan kes. Pakej multiprocessing telah diperkenalkan dalam Python versi 2.6, yang mereplikasi sepenuhnya satu set antara muka yang disediakan oleh threading untuk memudahkan penghijrahan. Satu-satunya perbezaan ialah ia menggunakan berbilang proses dan bukannya berbilang benang. Setiap proses mempunyai GIL bebasnya sendiri, jadi tidak akan ada perbalahan GIL antara proses.
Dengan pelbagai pemprosesan ini, anda boleh melengkapkan penukaran dengan mudah daripada satu proses kepada pelaksanaan serentak. Multiprocessing menyokong sub-proses, komunikasi dan perkongsian data, melaksanakan bentuk penyegerakan yang berbeza dan menyediakan komponen seperti Proses, Baris Gilir, Paip dan Kunci.
Selain berurusan dengan GIL Python, satu lagi sebab untuk multiprocessing ialah ketidakkonsistenan antara sistem pengendalian Windows dan sistem Linux/Unix.
Sistem pengendalian Unix/Linux menyediakan panggilan sistem fork(), yang sangat istimewa. Fungsi biasa dipanggil sekali dan kembali sekali, tetapi fork() dipanggil sekali dan kembali dua kali, kerana sistem pengendalian secara automatik menyalin proses semasa (proses induk) (proses anak), dan kemudian menyalinnya masing-masing dalam proses induk dan proses anak. . Proses anak sentiasa mengembalikan 0, dan proses induk mengembalikan ID proses anak. Sebabnya ialah proses induk boleh menghentikan banyak proses anak, jadi proses induk mesti merekodkan ID setiap proses anak, dan proses anak hanya perlu memanggil getpid() untuk mendapatkan ID proses induk.
Modul os Python merangkum panggilan sistem biasa, termasuk fork, yang boleh membuat proses anak dengan mudah dalam program Python:
import os print('Process (%s) start...' % os.getpid()) # Only works on Unix/Linux/Mac: pid = os.fork() if pid == 0: print('I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid())) else: print('I (%s) just created a child process (%s).' % (os.getpid(), pid))
Kod di atas adalah pada Linux, Unix dan Mac Hasil pelaksanaan ialah :
Process (876) start... I (876) just created a child process (877). I am child process (877) and my parent is 876.
Dengan panggilan fork, apabila proses menerima tugasan baharu, ia boleh menyalin proses anak untuk mengendalikan tugas baharu Pelayan Apache biasa mempunyai proses induk mendengar pada port ialah permintaan http baharu, proses anak bercabang untuk mengendalikan permintaan http baharu.
Memandangkan Windows tidak mempunyai panggilan fork, kod di atas tidak boleh dijalankan pada Windows. Memandangkan Python adalah platform silang, ia semestinya menyediakan sokongan berbilang proses merentas platform. Modul berbilang pemprosesan ialah versi merentas platform bagi modul berbilang proses. Modul multiprocessing merangkum panggilan fork() supaya kita tidak perlu memberi perhatian kepada butiran fork(). Memandangkan Windows tidak mempunyai panggilan fork, multiprocessing perlu "mensimulasikan" kesan fork.
Buat modul proses pengurusan:
Modul sub-proses penyegerakan:
Mari kita pelajari penggunaan khusus setiap komponen dan fungsi
Modul multiprocessing menyediakan kelas Proses untuk mewakili objek proses. .
Dalam pemproses berbilang, setiap proses diwakili oleh kelas Proses: Proses([kumpulan [, sasaran [, nama [, args [, kwargs]]]]])
实例方法:
属性介绍:
使用示例:(注意:在windows中Process()必须放到if name == ‘main’:下)
from multiprocessing import Process import os def run_proc(name): print('Run child process %s (%s)...' % (name, os.getpid())) if __name__=='__main__': print('Parent process %s.' % os.getpid()) p = Process(target=run_proc, args=('test',)) print('Child process will start.') p.start() p.join() print('Child process end.')
Pool类用于需要执行的目标很多,而手动限制进程数量又太繁琐时,如果目标少且不用控制进程数量则可以用Process类。Pool可以提供指定数量的进程,供用户调用,当有新的请求提交到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,就重用进程池中的进程。
构造方法:Pool([processes[, initializer[, initargs[, maxtasksperchild[, context]]]]])
实例方法:
方法apply_async()和map_async()的返回值是AsyncResul的实例obj。实例具有以下方法:
<span style="color: rgb(106, 115, 125); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);"># -*- coding:utf-8 -*-</span><br><span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">Queue(用于进程通信,资源共享)</span><br><span style="color: rgb(106, 115, 125); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);"># Pool+map</span><br><span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">from</span> <span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">multiprocessing</span> <span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">import</span> <span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">Pool</span><br><span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">def</span> <span style="color: rgb(0, 92, 197); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">test</span>(<span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">i</span>):<br><span style="color: rgb(111, 66, 193); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">print</span>(<span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">i</span>)<br><span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">if</span> <span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">__name__</span> <span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">==</span> <span style="color: rgb(102, 153, 0); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">"__main__"</span>:<br><span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">lists</span> <span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">=</span> <span style="color: rgb(111, 66, 193); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">range</span>(<span style="color: rgb(0, 92, 197); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">100</span>)<br><span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">pool</span> <span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">=</span> <span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">Pool</span>(<span style="color: rgb(0, 92, 197); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">8</span>)<br><span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">pool</span>.<span style="color: rgb(0, 92, 197); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">map</span>(<span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">test</span>, <span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">lists</span>)<br><span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">pool</span>.<span style="color: rgb(0, 92, 197); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">close</span>()<br><span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">pool</span>.<span style="color: rgb(0, 92, 197); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">join</span>()<br>
<span style="color: rgb(106, 115, 125); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);"># -*- coding:utf-8 -*-</span><br><span style="color: rgb(106, 115, 125); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);"># 异步进程池(非阻塞)</span><br><span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">from</span> <span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">multiprocessing</span> <span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">import</span> <span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">Pool</span><br><span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">def</span> <span style="color: rgb(0, 92, 197); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">test</span>(<span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">i</span>):<br><span style="color: rgb(111, 66, 193); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">print</span>(<span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">i</span>)<br><span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">if</span> <span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">__name__</span> <span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">==</span> <span style="color: rgb(102, 153, 0); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">"__main__"</span>:<br><span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">pool</span> <span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">=</span> <span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">Pool</span>(<span style="color: rgb(0, 92, 197); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">8</span>)<br><span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">for</span> <span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">i</span> <span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">in</span> <span style="color: rgb(111, 66, 193); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">range</span>(<span style="color: rgb(0, 92, 197); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">100</span>):<br><span style="color: rgb(102, 153, 0); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">'''</span><br><span style="color: rgb(102, 153, 0); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">For循环中执行步骤:</span><br><span style="color: rgb(102, 153, 0); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">(1)循环遍历,将100个子进程添加到进程池(相对父进程会阻塞)</span><br><span style="color: rgb(102, 153, 0); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">(2)每次执行8个子进程,等一个子进程执行完后,立马启动新的子进程。(相对父进程不阻塞)</span><br><span style="color: rgb(102, 153, 0); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">apply_async为异步进程池写法。异步指的是启动子进程的过程,与父进程本身的执行(print)是异步的,而For循环中往进程池添加子进程的过程,与父进程本身的执行却是同步的。</span><br><span style="color: rgb(102, 153, 0); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">'''</span><br><span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">pool</span>.<span style="color: rgb(0, 92, 197); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">apply_async</span>(<span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">test</span>, <span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">args</span><span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">=</span>(<span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">i</span>,))<span style="color: rgb(106, 115, 125); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);"># 维持执行的进程总数为8,当一个进程执行完后启动一个新进程.</span><br><span style="color: rgb(111, 66, 193); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">print</span>(<span style="color: rgb(102, 153, 0); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">"test"</span>)<br><span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">pool</span>.<span style="color: rgb(0, 92, 197); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">close</span>()<br><span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">pool</span>.<span style="color: rgb(0, 92, 197); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">join</span>()<br>
<span style="color: rgb(106, 115, 125); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);"># -*- coding:utf-8 -*-</span><br><span style="color: rgb(106, 115, 125); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);"># 异步进程池(非阻塞)</span><br><span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">from</span> <span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">multiprocessing</span> <span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">import</span> <span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">Pool</span><br><span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">def</span> <span style="color: rgb(0, 92, 197); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">test</span>(<span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">i</span>):<br><span style="color: rgb(111, 66, 193); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">print</span>(<span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">i</span>)<br><span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">if</span> <span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">__name__</span> <span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">==</span> <span style="color: rgb(102, 153, 0); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">"__main__"</span>:<br><span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">pool</span> <span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">=</span> <span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">Pool</span>(<span style="color: rgb(0, 92, 197); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">8</span>)<br><span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">for</span> <span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">i</span> <span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">in</span> <span style="color: rgb(111, 66, 193); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">range</span>(<span style="color: rgb(0, 92, 197); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">100</span>):<br><span style="color: rgb(102, 153, 0); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">'''</span><br><span style="color: rgb(102, 153, 0); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">实际测试发现,for循环内部执行步骤:</span><br><span style="color: rgb(102, 153, 0); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">(1)遍历100个可迭代对象,往进程池放一个子进程</span><br><span style="color: rgb(102, 153, 0); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">(2)执行这个子进程,等子进程执行完毕,再往进程池放一个子进程,再执行。(同时只执行一个子进程)</span><br><span style="color: rgb(102, 153, 0); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">for循环执行完毕,再执行print函数。</span><br><span style="color: rgb(102, 153, 0); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">'''</span><br><span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">pool</span>.<span style="color: rgb(0, 92, 197); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">apply</span>(<span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">test</span>, <span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">args</span><span style="color: rgb(215, 58, 73); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">=</span>(<span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">i</span>,))<span style="color: rgb(106, 115, 125); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);"># 维持执行的进程总数为8,当一个进程执行完后启动一个新进程.</span><br><span style="color: rgb(111, 66, 193); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">print</span>(<span style="color: rgb(102, 153, 0); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">"test"</span>)<br><span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">pool</span>.<span style="color: rgb(0, 92, 197); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">close</span>()<br><span style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">pool</span>.<span style="color: rgb(0, 92, 197); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">join</span>()<br>
在使用多进程的过程中,最好不要使用共享资源。普通的全局变量是不能被子进程所共享的,只有通过Multiprocessing组件构造的数据结构可以被共享。
Queue是用来创建进程间资源共享的队列的类,使用Queue可以达到多进程间数据传递的功能(缺点:只适用Process类,不能在Pool进程池中使用)。
构造方法:Queue([maxsize])
实例方法:
使用示例:
from multiprocessing import Process, Queue import os, time, random def write(q): print('Process to write: %s' % os.getpid()) for value in ['A', 'B', 'C']: print('Put %s to queue...' % value) q.put(value) time.sleep(random.random()) def read(q): print('Process to read: %s' % os.getpid()) while True: value = q.get(True) print('Get %s from queue.' % value) if __name__ == "__main__": q = Queue() pw = Process(target=write, args=(q,)) pr = Process(target=read, args=(q,)) pw.start() pr.start() pw.join()# 等待pw结束 pr.terminate()# pr进程里是死循环,无法等待其结束,只能强行终止
JoinableQueue就像是一个Queue对象,但队列允许项目的使用者通知生成者项目已经被成功处理。通知进程是使用共享的信号和条件变量来实现的。
构造方法:JoinableQueue([maxsize])
实例方法
JoinableQueue的实例p除了与Queue对象相同的方法之外还具有:
使用示例:
# -*- coding:utf-8 -*- from multiprocessing import Process, JoinableQueue import time, random def consumer(q): while True: res = q.get() print('消费者拿到了 %s' % res) q.task_done() def producer(seq, q): for item in seq: time.sleep(random.randrange(1,2)) q.put(item) print('生产者做好了 %s' % item) q.join() if __name__ == "__main__": q = JoinableQueue() seq = ('产品%s' % i for i in range(5)) p = Process(target=consumer, args=(q,)) p.daemon = True# 设置为守护进程,在主线程停止时p也停止,但是不用担心,producer内调用q.join保证了consumer已经处理完队列中的所有元素 p.start() producer(seq, q) print('主线程')
multiprocessing 中Value和Array的实现原理都是在共享内存中创建ctypes()对象来达到共享数据的目的,两者实现方法大同小异,只是选用不同的ctypes数据类型而已。
构造方法:Value((typecode_or_type, args[, lock])
typecode_or_type支持的类型:
| Type code | C Type | Python Type | Minimum size in bytes | | --------- | ------------------ | ----------------- | --------------------- | | `'b'` | signed char| int | 1 | | `'B'` | unsigned char| int | 1 | | `'u'` | Py_UNICODE | Unicode character | 2 | | `'h'` | signed short | int | 2 | | `'H'` | unsigned short | int | 2 | | `'i'` | signed int | int | 2 | | `'I'` | unsigned int | int | 2 | | `'l'` | signed long| int | 4 | | `'L'` | unsigned long| int | 4 | | `'q'` | signed long long | int | 8 | | `'Q'` | unsigned long long | int | 8 | | `'f'` | float| float | 4 | | `'d'` | double | float | 8 |
参考地址:https://docs.python.org/3/library/array.html
构造方法:Array(typecode_or_type, size_or_initializer, **kwds[, lock])
使用示例:
import multiprocessing def f(n, a): n.value = 3.14 a[0] = 5 if __name__ == '__main__': num = multiprocessing.Value('d', 0.0) arr = multiprocessing.Array('i', range(10)) p = multiprocessing.Process(target=f, args=(num, arr)) p.start() p.join() print(num.value) print(arr[:])
注意:Value和Array只适用于Process类。
多进程还有一种数据传递方式叫管道原理和 Queue相同。Pipe可以在进程之间创建一条管道,并返回元组(conn1,conn2),其中conn1,conn2表示管道两端的连接对象,强调一点:必须在产生Process对象之前产生管道。
构造方法:Pipe([duplex])
实例方法:
使用示例:
from multiprocessing import Process, Pipe import time # 子进程执行方法 def f(Subconn): time.sleep(1) Subconn.send("吃了吗") print("来自父亲的问候:", Subconn.recv()) Subconn.close() if __name__ == "__main__": parent_conn, child_conn = Pipe()# 创建管道两端 p = Process(target=f, args=(child_conn,))# 创建子进程 p.start() print("来自儿子的问候:", parent_conn.recv()) parent_conn.send("嗯")
Manager()返回的manager对象控制了一个server进程,此进程包含的python对象可以被其他的进程通过proxies来访问。从而达到多进程间数据通信且安全。Manager模块常与Pool模块一起使用。
Manager支持的类型有list,dict,Namespace,Lock,RLock,Semaphore,BoundedSemaphore,Condition,Event,Queue,Value和Array。
管理器是独立运行的子进程,其中存在真实的对象,并以服务器的形式运行,其他进程通过使用代理访问共享对象,这些代理作为客户端运行。Manager()是BaseManager的子类,返回一个启动的SyncManager()实例,可用于创建共享对象并返回访问这些共享对象的代理。
BaseManager,创建管理器服务器的基类
构造方法:BaseManager([address[, authkey]])
实例方法:
实例属性:
SyncManager,以下类型均不是进程安全的,需要加锁..
实例方法:
使用示例:
import multiprocessing def f(x, arr, l, d, n): x.value = 3.14 arr[0] = 5 l.append('Hello') d[1] = 2 n.a = 10 if __name__ == '__main__': server = multiprocessing.Manager() x = server.Value('d', 0.0) arr = server.Array('i', range(10)) l = server.list() # 子进程执行方法 def f(Subconn): time.sleep(1) Subconn.send("吃了吗") print("来自父亲的问候:", Subconn.recv()) print(x.value) print(arr) print(l) print(d) print(n)
Lock锁的作用是当多个进程需要访问共享资源的时候,避免访问的冲突。加锁保证了多个进程修改同一块数据时,同一时间只能有一个修改,即串行的修改,牺牲了速度但保证了数据安全。Lock包含两种状态——锁定和非锁定,以及两个基本的方法。
构造方法:Lock()
实例方法:
使用示例:
from multiprocessing import Process, Lock def l(lock, num): lock.acquire() print("Hello Num: %s" % (num)) lock.release() if __name__ == '__main__': lock = Lock()# 这个一定要定义为全局 for num in range(20): Process(target=l, args=(lock, num)).start()
RLock(可重入锁)是一个可以被同一个线程请求多次的同步指令。RLock使用了“拥有的线程”和“递归等级”的概念,处于锁定状态时,RLock被某个线程拥有。拥有RLock的线程可以再次调用acquire(),释放锁时需要调用release()相同次数。可以认为RLock包含一个锁定池和一个初始值为0的计数器,每次成功调用 acquire()/release(),计数器将+1/-1,为0时锁处于未锁定状态。
构造方法:RLock()
实例方法:
信号量是一个更高级的锁机制。信号量内部有一个计数器而不像锁对象内部有锁标识,而且只有当占用信号量的线程数超过信号量时线程才阻塞。这允许了多个线程可以同时访问相同的代码区。比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去,如果指定信号量为3,那么来一个人获得一把锁,计数加1,当计数等于3时,后面的人均需要等待。一旦释放,就有人可以获得一把锁。
构造方法:Semaphore([value])
实例方法:
使用示例:
from multiprocessing import Process, Semaphore import time, random def go_wc(sem, user): sem.acquire() print('%s 占到一个茅坑' % user) time.sleep(random.randint(0, 3)) sem.release() print(user, 'OK') if __name__ == '__main__': sem = Semaphore(2) p_l = [] for i in range(5): p = Process(target=go_wc, args=(sem, 'user%s' % i,)) p.start() p_l.append(p) for i in p_l: i.join()
可以把Condition理解为一把高级的锁,它提供了比Lock, RLock更高级的功能,允许我们能够控制复杂的线程同步问题。Condition在内部维护一个锁对象(默认是RLock),可以在创建Condigtion对象的时候把琐对象作为参数传入。Condition也提供了acquire, release方法,其含义与锁的acquire, release方法一致,其实它只是简单的调用内部锁对象的对应的方法而已。Condition还提供了其他的一些方法。
构造方法:Condition([lock/rlock])
实例方法:
使用示例:
import multiprocessing import time def stage_1(cond): """perform first stage of work, then notify stage_2 to continue """ name = multiprocessing.current_process().name print('Starting', name) with cond: print('{} done and ready for stage 2'.format(name)) cond.notify_all() def stage_2(cond): """wait for the condition telling us stage_1 is done""" name = multiprocessing.current_process().name print('Starting', name) with cond: cond.wait() print('{} running'.format(name)) if __name__ == '__main__': condition = multiprocessing.Condition() s1 = multiprocessing.Process(name='s1', target=stage_1, args=(condition,)) s2_clients = [ multiprocessing.Process( name='stage_2[{}]'.format(i), target=stage_2, args=(condition,), ) for i in range(1, 3) ] for c in s2_clients: c.start() time.sleep(1) s1.start() s1.join() for c in s2_clients: c.join()
Event内部包含了一个标志位,初始的时候为false。可以使用set()来将其设置为true;或者使用clear()将其从新设置为false;可以使用is_set()来检查标志位的状态;另一个最重要的函数就是wait(timeout=None),用来阻塞当前线程,直到event的内部标志位被设置为true或者timeout超时。如果内部标志位为true则wait()函数理解返回。
使用示例:
import multiprocessing import time def wait_for_event(e): """Wait for the event to be set before doing anything""" print('wait_for_event: starting') e.wait() print('wait_for_event: e.is_set()->', e.is_set()) def wait_for_event_timeout(e, t): """Wait t seconds and then timeout""" print('wait_for_event_timeout: starting') e.wait(t) print('wait_for_event_timeout: e.is_set()->', e.is_set()) if __name__ == '__main__': e = multiprocessing.Event() w1 = multiprocessing.Process( name='block', target=wait_for_event, args=(e,), ) w1.start() w2 = multiprocessing.Process( name='nonblock', target=wait_for_event_timeout, args=(e, 2), ) w2.start() print('main: waiting before calling Event.set()') time.sleep(3) e.set() print('main: event is set')
multiprocessing.dummy 模块与 multiprocessing 模块的区别:dummy 模块是多线程,而 multiprocessing 是多进程, api 都是通用的。所有可以很方便将代码在多线程和多进程之间切换。multiprocessing.dummy通常在IO场景可以尝试使用,比如使用如下方式引入线程池。
from multiprocessing.dummy import Pool as ThreadPool
multiprocessing.dummy与早期的threading,不同的点好像是在多多核CPU下,只绑定了一个核心(具体未考证)。
参考文档:
Python标准库为我们提供了threading和multiprocessing模块编写相应的多线程/多进程代码。从Python3.2开始,标准库为我们提供了concurrent.futures模块,它提供了ThreadPoolExecutor和ProcessPoolExecutor两个类,实现了对threading和multiprocessing的更高级的抽象,对编写线程池/进程池提供了直接的支持。concurrent.futures基础模块是executor和future。
Executor是一个抽象类,它不能被直接使用。它为具体的异步执行定义了一些基本的方法。ThreadPoolExecutor和ProcessPoolExecutor继承了Executor,分别被用来创建线程池和进程池的代码。
ThreadPoolExecutor类是Executor子类,使用线程池执行异步调用。
class concurrent.futures.ThreadPoolExecutor(max_workers)
使用max_workers数目的线程池执行异步调用。
ThreadPoolExecutor类是Executor子类,使用进程池执行异步调用。
class concurrent.futures.ProcessPoolExecutor(max_workers=None)
使用max_workers数目的进程池执行异步调用,如果max_workers为None则使用机器的处理器数目(如4核机器max_worker配置为None时,则使用4个进程进行异步并发)。
Executor中定义了submit()方法,这个方法的作用是提交一个可执行的回调task,并返回一个future实例。future对象代表的就是给定的调用。
Executor.submit(fn, *args, **kwargs)
使用示例:
from concurrent import futures def test(num): import time return time.ctime(), num with futures.ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(test, 1) print(future.result())
除了submit,Exectuor还为我们提供了map方法,这个方法返回一个map(func, *iterables)迭代器,迭代器中的回调执行返回的结果有序的。
Executor.map(func, *iterables, timeout=None)
使用示例:
from concurrent import futures def test(num): import time return time.ctime(), num data = [1, 2, 3] with futures.ThreadPoolExecutor(max_workers=1) as executor: for future in executor.map(test, data): print(future)
释放系统资源,在Executor.submit()或 Executor.map()等异步操作后调用。使用with语句可以避免显式调用此方法。
Executor.shutdown(wait=True)
Future可以理解为一个在未来完成的操作,这是异步编程的基础。通常情况下,我们执行io操作,访问url时(如下)在等待结果返回之前会产生阻塞,cpu不能做其他事情,而Future的引入帮助我们在等待的这段时间可以完成其他的操作。
Future类封装了可调用的异步执行。Future 实例通过 Executor.submit()方法创建。
使用示例:
from concurrent.futures import ThreadPoolExecutor, wait, as_completed from time import sleep from random import randint def return_after_5_secs(num): sleep(randint(1, 5)) return "Return of {}".format(num) pool = ThreadPoolExecutor(5) futures = [] for x in range(5): futures.append(pool.submit(return_after_5_secs, x)) print(1) for x in as_completed(futures): print(x.result()) print(2)
参考链接:
Atas ialah kandungan terperinci Python berbilang benang dan susunan terperinci berbilang proses. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!