Python多線程及其基本使用方法實(shí)例分析
本文實(shí)例講述了Python多線程及其基本使用方法。分享給大家供大家參考,具體如下:
學(xué)習(xí)Python的多線程(Multi-threading),至少應(yīng)該要有進(jìn)程與線程的基本概念,可以參考:http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html。
1.Python中的多線程
執(zhí)行一個(gè)程序,即在操作系統(tǒng)中開啟了一個(gè)進(jìn)程,在某一時(shí)刻,一個(gè)CPU內(nèi)核只能進(jìn)行一個(gè)進(jìn)程的任務(wù),現(xiàn)在的計(jì)算機(jī)所說(shuō)的多進(jìn)程/多任務(wù)其實(shí)是通過(guò)加快CPU的執(zhí)行速度來(lái)實(shí)現(xiàn)的,因?yàn)橐粋€(gè)CPU每秒能執(zhí)行上億次的計(jì)算,能夠?qū)M(jìn)程進(jìn)行很多次切換,所以在人為可以感知的時(shí)間里,看上去,計(jì)算機(jī)確實(shí)是在同時(shí)執(zhí)行多個(gè)程序,即同時(shí)處理多個(gè)進(jìn)程。
一個(gè)進(jìn)程中可以包含有多個(gè)線程,這多個(gè)線程為實(shí)現(xiàn)該進(jìn)程的某個(gè)主要功能而運(yùn)行著,多個(gè)線程可以進(jìn)行串行工作,也可以并發(fā)同時(shí)進(jìn)行工作,顯然后者可以節(jié)省更多的時(shí)間。
在Python中是支持多線程并發(fā)執(zhí)行的,只是Python中的多線程只能利用單核,也就是說(shuō)Python中的某一個(gè)進(jìn)程的多個(gè)線程只能在一個(gè)CPU核心上運(yùn)行,而不能分配在多個(gè)CPU核心中運(yùn)行,這是考慮到線程安全的緣故,而Python中的GIL則保證了線程安全。關(guān)于Python中的GIL,可以參考下面一篇文章:《淺析Python的GIL和線程安全》。
下面是自己在學(xué)習(xí)過(guò)程中的一些課堂筆記,因?yàn)檫€沒(méi)有真正學(xué)習(xí)一些理論,所以可能會(huì)有些錯(cuò)誤,但目前是方便自己的理解:
即GLI是以CPU核心為單位來(lái)控制全局鎖,所以是不能跨不同的CPU(核心 )的GLI可以保證同一個(gè)進(jìn)程中,某一個(gè)線程的共享數(shù)據(jù)在某一時(shí)刻只能同時(shí)被另外一個(gè)線程修改(使用),而不能同時(shí)被多個(gè)線程修改(使用),如果去掉GLI,則需要自己為線程加鎖,這樣之后,性能比原來(lái)還要差。
當(dāng)然,難道就不能充分利用多核CPU或多個(gè)CPU了?
做成多進(jìn)程就可以了,不同的進(jìn)程運(yùn)行在不同的CPU(核心)上,也可以實(shí)現(xiàn)并發(fā),只是這樣的話就會(huì)比較浪費(fèi)內(nèi)存空間,考慮同時(shí)運(yùn)行10個(gè)QQ程序的情況,假如1個(gè)QQ占用500M的內(nèi)存空間,則10個(gè)QQ就要占用5G的內(nèi)存空間了。但如果是多線程的話,可能10個(gè)QQ還是共享著這500M的內(nèi)存空間。還有一個(gè)缺點(diǎn)就是,多進(jìn)程間的數(shù)據(jù)直接訪問(wèn)可能會(huì)比較麻煩,但其實(shí)也是可以實(shí)現(xiàn)的,比如chrome瀏覽器就是用多進(jìn)程實(shí)現(xiàn)的。
目前首先要明確的是,Python中是不能把一個(gè)進(jìn)程的多個(gè)線程分布在不同的CPU核心上運(yùn)行的。
2.Python多線程使用方法1
給出下面的程序代碼及注釋:
import threading #Python多線程模塊 import time def run(num): print 'Hi, I am thread %s..lalala' % num time.sleep(1) for i in range(20): t = threading.Thread(target=run, args=(i,)) #多線程使用方法,target為需要執(zhí)行多線程的函數(shù),args為函數(shù)中的參數(shù),注意這里的參數(shù)寫成(i,),即如果只能一個(gè)參數(shù),也要加上一個(gè)"," t.start() #開始執(zhí)行多線程
程序運(yùn)行結(jié)果如下:
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day6$ python thread4.py
Hi, I am thread 0..lalala
Hi, I am thread 1..lalala
Hi, I am thread 2..lalala
Hi, I am thread 3..lalala
Hi, I am thread 4..lalala
Hi, I am thread 5..lalala
Hi, I am thread 6..lalala
Hi, I am thread 7..lalala
Hi, I am thread 8..lalala
Hi, I am thread 9..lalala
Hi, I am thread 10..lalala
Hi, I am thread 11..lalala
Hi, I am thread 12..lalala
Hi, I am thread 13..lalala
Hi, I am thread 14..lalala
Hi, I am thread 15..lalala
Hi, I am thread 16..lalala
Hi, I am thread 17..lalala
Hi, I am thread 18..lalala
Hi, I am thread 19..lalala
直接看執(zhí)行結(jié)果是看不出什么的,這里說(shuō)一下這個(gè)程序的執(zhí)行過(guò)程:0到19是同時(shí)打印輸入的,在打印19后,程序sleep 1秒后才結(jié)束程序的運(yùn)行。
上面這個(gè)程序有20個(gè)線程執(zhí)行,每個(gè)線程都是:打印字符串+sleep(1)。我們實(shí)際看到的結(jié)果是0到19同時(shí)打印,然后才sleep 1秒,但是需要注意的是,并非是20個(gè)線程才執(zhí)行一次sleep(1),而是在每個(gè)線程中都執(zhí)行了一次sleep(1),即該程序?qū)嶋H上是執(zhí)行了20次sleep(1),而我們實(shí)際看到的結(jié)果是程序運(yùn)行時(shí)僅僅是暫停了1秒,那是因?yàn)檫@20次sleep(1)是并發(fā)執(zhí)行的。
上面的程序可以這么去理解:20個(gè)線程相當(dāng)于有20匹馬,20匹馬同時(shí)起跑(打印字符串),然后以同時(shí)停1秒(sleep(1)),最后同時(shí)到達(dá)終點(diǎn)(20個(gè)線程運(yùn)行結(jié)束,即程序執(zhí)行結(jié)束)。
為了更好的理解上面的程序,可以把上面的代碼改為如下:
import threading import time def run(num): print 'Hi, I am thread %s..lalala' % num time.sleep(1) for i in range(20): t = threading.Thread(target=run, args=(i,)) t.start() t.join() #等上一個(gè)線程執(zhí)行完后再執(zhí)行下一個(gè)線程
執(zhí)行結(jié)果如下:
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day6$ python thread4.py
Hi, I am thread 0..lalala
Hi, I am thread 1..lalala
Hi, I am thread 2..lalala
Hi, I am thread 3..lalala
Hi, I am thread 4..lalala
Hi, I am thread 5..lalala
Hi, I am thread 6..lalala
Hi, I am thread 7..lalala
Hi, I am thread 8..lalala
Hi, I am thread 9..lalala
Hi, I am thread 10..lalala
Hi, I am thread 11..lalala
Hi, I am thread 12..lalala
Hi, I am thread 13..lalala
Hi, I am thread 14..lalala
Hi, I am thread 15..lalala
Hi, I am thread 16..lalala
Hi, I am thread 17..lalala
Hi, I am thread 18..lalala
Hi, I am thread 19..lalala
執(zhí)行結(jié)果看上去跟前面是一樣的,但執(zhí)行過(guò)程卻是這樣的:每打印一次字符串,再暫停一秒。
通過(guò)這個(gè)程序,也就可以更好的理解Python的多線程并發(fā)執(zhí)行了,當(dāng)然,因?yàn)檫@是一個(gè)動(dòng)態(tài)的過(guò)程,所以把程序執(zhí)行一遍后會(huì)有更好的理解。
3.Python多線程使用方法2
程序代碼如下:
import threading,time class MyThread(threading.Thread): def __init__(self, num): threading.Thread.__init__(self) self.num = num def run(self): #this name must be 'run' print 'I am thread %s' % self.num time.sleep(2) for i in range(20): t = MyThread(i) t.start()
程序的執(zhí)行結(jié)果與方法1是一樣的,這里就不給出了,只是這里利用了面向?qū)ο缶幊痰乃枷敕椒▉?lái)設(shè)計(jì)程序代碼。
更多關(guān)于Python相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Python進(jìn)程與線程操作技巧總結(jié)》、《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》、《Python入門與進(jìn)階經(jīng)典教程》、《Python+MySQL數(shù)據(jù)庫(kù)程序設(shè)計(jì)入門教程》及《Python常見(jiàn)數(shù)據(jù)庫(kù)操作技巧匯總》
希望本文所述對(duì)大家Python程序設(shè)計(jì)有所幫助。
- 詳解Python中的多線程編程
- python多線程編程中的join函數(shù)使用心得
- Python中多線程thread與threading的實(shí)現(xiàn)方法
- 淺析Python中的多進(jìn)程與多線程的使用
- 理解python多線程(python多線程簡(jiǎn)明教程)
- 基python實(shí)現(xiàn)多線程網(wǎng)頁(yè)爬蟲
- Python threading多線程編程實(shí)例
- Python實(shí)現(xiàn)快速多線程ping的方法
- Python控制多進(jìn)程與多線程并發(fā)數(shù)總結(jié)
- Python多線程、異步+多進(jìn)程爬蟲實(shí)現(xiàn)代碼
相關(guān)文章
Python爬蟲進(jìn)階之爬取某視頻并下載的實(shí)現(xiàn)
這篇文章主要介紹了Python爬蟲進(jìn)階之爬取某視頻并下載的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12Python實(shí)現(xiàn)的爬取百度文庫(kù)功能示例
這篇文章主要介紹了Python實(shí)現(xiàn)的爬取百度文庫(kù)功能,結(jié)合實(shí)例形式分析了Python針對(duì)百度文庫(kù)的爬取、編碼轉(zhuǎn)換、文件保存等相關(guān)操作技巧,需要的朋友可以參考下2019-02-02Python實(shí)現(xiàn)對(duì)文件類型的獲取方法
在工作中時(shí)常需要對(duì)文件進(jìn)行各種處理,如上傳下載,壓縮解壓等,需要獲取文件的類型,所以本文給大家介紹了使用Python實(shí)現(xiàn)對(duì)文件類型的獲取方法,文中通過(guò)代碼示例講解的非常詳細(xì),需要的朋友可以參考下2024-08-08使用Python操作Excel中的各項(xiàng)頁(yè)面設(shè)置功能
在使用Excel進(jìn)行數(shù)據(jù)分析或報(bào)告制作時(shí),頁(yè)面設(shè)置是確保最終輸出效果專業(yè)、美觀的關(guān)鍵步驟,合理的頁(yè)面設(shè)置不僅能夠優(yōu)化打印效果,還能提升數(shù)據(jù)的可讀性,本文將詳細(xì)介紹如何使用Python操作Excel中的各項(xiàng)頁(yè)面設(shè)置功能,需要的朋友可以參考下2024-08-08