目錄
- 一.Python 線程解釋
- 二.Python 線程創(chuàng)建和啟動
- 三.Python 線程傳參
- 四.Python 線程結(jié)束
- 五.Python 線程相關(guān)函數(shù)介紹
- 六.Python 線程重點(diǎn)總結(jié)
- 七.猜你喜歡
零基礎(chǔ) Python 學(xué)習(xí)路線推薦 : Python 學(xué)習(xí)目錄 >> Python 基礎(chǔ)入門
在以前的文章中雖然我們沒有介紹過線程這個(gè)概念,但是實(shí)際上前面所有代碼都是線程敬尺,只不過是單線程,代碼由上而下依次執(zhí)行或者進(jìn)入 main 函數(shù)執(zhí)行蜻直,這樣的單線程也稱為主線程。
有了單線程的話到腥,什么又是多線程?可以這么理解:一個(gè)線程執(zhí)行一個(gè)代碼塊晋辆,多個(gè)線程可以同時(shí)執(zhí)行多個(gè)代碼,使用多線程能讓程序效率更高霸饲。舉個(gè)例子,你今天有兩件事需要完成,分別是洗衣服和打掃房間中捆,分別來看看單線程和多線程如何完成:
單線程:先用洗衣機(jī)洗衣服30分鐘,等衣服洗完之后再打掃房間60分鐘蟋滴,累計(jì)總耗時(shí):90分鐘;
多線程:把衣服放到洗衣機(jī)并且30分鐘后自動結(jié)束球散,然后立刻開始打掃房間60分鐘悲龟,累計(jì)耗時(shí):60分鐘斩芭;
由此可見挤土,完成同樣的事情,單線程是一件事情做完之后繼續(xù)下一件事情,而多線程可以同時(shí)執(zhí)行多件事情止邮,所以多線程比單線程效率更高!
一.Python 線程解釋
線程是 cpu 最小調(diào)度單位撩匕,一個(gè)程序中至少有一個(gè)或者多個(gè)線程(至于進(jìn)程暫時(shí)不做講解,后面文章會有詳細(xì)解釋)扁凛!在開發(fā)中使用線程可以讓程序運(yùn)行效率更高,多線程類似于同時(shí)執(zhí)行多個(gè)不同代碼塊字币。
二.Python 線程創(chuàng)建和啟動
1.導(dǎo)入線程模塊
# 導(dǎo)入線程threading模塊
import threading
2.創(chuàng)建線程并初始化線程
調(diào)用 threading 模塊中的缺省函數(shù) Thread ,創(chuàng)建并初始化線程翩活,返回線程句柄澄峰。如果對缺省函數(shù)已經(jīng)忘記的小伙伴請回到 Python 函數(shù)的聲明和定義中關(guān)于缺省參數(shù)部分復(fù)習(xí)一下绸硕。
# 創(chuàng)建并初始化線程出嘹,返回線程句柄
t = threading.Thread(target=函數(shù)名)
3.啟動線程
通過初始化返回的線程句柄調(diào)用 start 函數(shù),啟動線程郎仆,此時(shí)會自動執(zhí)行在創(chuàng)建線程時(shí) target 對應(yīng)的函數(shù)內(nèi)部的代碼:
# 啟動線程
t.start()
綜合上面三步,下面使用代碼對 Python 線程 thread 做詳細(xì)講解:
# !usr/bin/env python
# -*- coding:utf-8 _*-
"""
@Author:猿說編程
@Blog(個(gè)人博客地址): www.codersrc.com
@File:Python 線程創(chuàng)建和傳參.py
@Time:2021/04/24 08:00
@Motto:不積跬步無以至千里,不積小流無以成江海曙旭,程序人生的精彩需要堅(jiān)持不懈地積累!
"""
# 導(dǎo)入線程threading模塊
import threading
# 導(dǎo)入內(nèi)置模塊time
import time
def wash_clothes():
print("洗衣服開始...")
# sleep 5 秒剂习,默認(rèn)以秒為單位
time.sleep(5)
print("洗衣服完成...")
def clean_room():
print("打掃房間開始...")
# sleep 5 秒,默認(rèn)以秒為單位
time.sleep(5)
print("打掃房間完成...")
if __name__ == "__main__":
# 創(chuàng)建線程并初始化 -- 該線程執(zhí)行wash_clothes中的代碼
t1 = threading.Thread(target=wash_clothes)
# 創(chuàng)建線程并初始化 -- 該線程執(zhí)行clean_room中的代碼
t2 = threading.Thread(target=clean_room)
t1.start()
t2.start()
'''
輸出結(jié)果:
洗衣服開始...
打掃房間開始...
洗衣服完成...
打掃房間完成...
'''
運(yùn)行程序可以發(fā)現(xiàn)程序從運(yùn)行開始到結(jié)束觅够,一共耗時(shí) 5 秒時(shí)間贴见!注意觀察輸出日志:
- 第一步:洗衣服開始和打掃房間開始幾乎同時(shí)開始档悠,兩個(gè)事件同時(shí)執(zhí)行.
- 第二步:程序停止 5 秒;
- 第三步:洗衣服和打掃房間幾乎同時(shí)完成
當(dāng)然你也可以按照以前的學(xué)習(xí)的內(nèi)容,先調(diào)用 wash_clothes 函數(shù)啦吧,在調(diào)用 clean_room 函數(shù),同樣能輸出內(nèi)容,而耗時(shí)卻是 10 秒左右郁妈,示例代碼如下:
# !usr/bin/env python
# -*- coding:utf-8 _*-
"""
@Author:猿說編程
@Blog(個(gè)人博客地址): www.codersrc.com
@File:Python 線程創(chuàng)建和傳參.py
@Time:2021/04/24 08:00
@Motto:不積跬步無以至千里胃碾,不積小流無以成江海俄周,程序人生的精彩需要堅(jiān)持不懈地積累波势!
"""
# 導(dǎo)入內(nèi)置模塊time
import time
def wash_clothes():
print("洗衣服開始...")
# sleep 5 秒闭翩,默認(rèn)以秒為單位
time.sleep(5)
print("洗衣服完成...")
def clean_room():
print("打掃房間開始...")
# sleep 5 秒,默認(rèn)以秒為單位
time.sleep(5)
print("打掃房間完成...")
if __name__ == "__main__":
wash_clothes()
clean_room()
'''
輸出結(jié)果:
洗衣服開始...
洗衣服完成...
打掃房間開始...
打掃房間完成...
'''
運(yùn)行程序可以發(fā)現(xiàn)程序從運(yùn)行開始到結(jié)束,一共耗時(shí) 10 秒時(shí)間逞怨!注意觀察輸出日志:
- 第一步:洗衣服開始叠赦;
- 第二步:程序停止了 5 秒;
- 第三步:洗衣服完成册踩,打掃房間開始
- 第四步:程序停止 5 秒;
- 第五步:打掃房間結(jié)束慕的,程序結(jié)束;
由此可見:多線程可以同時(shí)運(yùn)行多個(gè)任務(wù)俯邓,效率遠(yuǎn)比單線程更高!
三.Python 線程傳參
在上面的例子中朦蕴,我們并沒有為線程傳遞參數(shù),如果在線程中需要傳遞參數(shù)怎么辦呢?
threading.Thread 函數(shù)中有兩個(gè)缺省參數(shù) args 和 kwargs 雨饺,args 是元組類型,kwargs 是字典類型,缺省值默認(rèn)為空向瓷,除此之外,其實(shí)還可以設(shè)置線程的名字等超升,其函數(shù)聲明如下:
(ps:如果對缺省函數(shù)已經(jīng)忘記的小伙伴請回到 Python 函數(shù)的聲明和定義中關(guān)于缺省參數(shù)部分復(fù)習(xí)一下)
# !usr/bin/env python
# -*- coding:utf-8 _*-
"""
@Author:猿說編程
@Blog(個(gè)人博客地址): www.codersrc.com
@File:Python 線程創(chuàng)建和傳參.py
@Time:2021/04/24 08:00
@Motto:不積跬步無以至千里盈滴,不積小流無以成江海病苗,程序人生的精彩需要堅(jiān)持不懈地積累!
"""
def __init__(self, group=None, target=None, name=None,
args=(), kwargs=None, *, daemon=None):
"""This constructor should always be called with keyword arguments. Arguments are:
*group* should be None; reserved for future extension when a ThreadGroup
class is implemented.
*target* is the callable object to be invoked by the run()
method. Defaults to None, meaning nothing is called.
*name* is the thread name. By default, a unique name is constructed of
the form "Thread-N" where N is a small decimal number.
*args* is the argument tuple for the target invocation. Defaults to ().
*kwargs* is a dictionary of keyword arguments for the target
invocation. Defaults to {}.
If a subclass overrides the constructor, it must make sure to invoke
the base class constructor (Thread.__init__()) before doing anything
else to the thread.
"""
示例代碼如下:
# !usr/bin/env python
# -*- coding:utf-8 _*-
"""
@Author:猿說編程
@Blog(個(gè)人博客地址): www.codersrc.com
@File:Python 線程創(chuàng)建和傳參.py
@Time:2021/04/24 08:00
@Motto:不積跬步無以至千里瞒斩,不積小流無以成江海,程序人生的精彩需要堅(jiān)持不懈地積累蔑鹦!
"""
# 導(dǎo)入線程threading模塊
import threading
# 導(dǎo)入內(nèi)置模塊time
import time
def wash_clothes(*args,**kargcs):
print("wash_clothes:",args)
print("wash_clothes:", kargcs)
def clean_room(*args,**kargcs):
print("clean_room:",args)
print("clean_room:", kargcs)
if __name__ == "__main__":
# args 傳遞元組柬帕,可以同時(shí)傳遞多個(gè)數(shù)據(jù)
# kwargs 傳遞字典,可以同時(shí)傳遞多個(gè)鍵值對
t1 = threading.Thread(target=wash_clothes,args=(1,"猿說python"),kwargs={"a":1,"b":False})
# args 傳遞元組,可以同時(shí)傳遞多個(gè)數(shù)據(jù)
# kwargs 傳遞字典仔引,可以同時(shí)傳遞多個(gè)鍵值對
t2 = threading.Thread(target=clean_room,args=(2,False),kwargs={"c":0.2,"d":False})
t1.start()
t2.start()
四.Python 線程結(jié)束
值得思考的是:在上面這份代碼中一共有幾個(gè)線程呢?并非兩個(gè)儿倒,一共是三個(gè)線程:
- 線程一:__name__ == “__main__” 作為主線程彻犁;
- 線程二:t1 作為子線程溉瓶;
- 線程三:t2 作為子線程疾宏;
注意:主程序會等待所有子程序結(jié)束之后才會結(jié)束!
五.Python 線程相關(guān)函數(shù)介紹
- 1.threading.Thread — 創(chuàng)建線程并初始化線程,可以為線程傳遞參數(shù) 蛀恩;
- 2.threading.enumerate — 返回一個(gè)包含正在運(yùn)行的線程的 list;
- 3.threading.activeCount — 返回正在運(yùn)行的線程數(shù)量顽馋,與 len(threading.enumerate)有相同的結(jié)果;
- 4.Thread.start — 啟動線程 ;
- 5.Thread.join — 阻塞函數(shù)聂宾,一直等到線程結(jié)束為止 ;
- 6.Thread.isAlive — 返回線程是否活動的许赃;
- 7.Thread.getName — 返回線程名;
- 8.Thread.setName — 設(shè)置線程名;
- 9.Thread.setDaemon — 設(shè)置為后臺線程沟于,這里默認(rèn)是 False,設(shè)置為 True 之后則主線程不會再等待子線程結(jié)束才結(jié)束存崖,而是主線程結(jié)束意味程序退出,子線程也立即結(jié)束,注意調(diào)用時(shí)必須設(shè)置在 start 之前军浆;
簡單的示例代碼:
# !usr/bin/env python
# -*- coding:utf-8 _*-
"""
@Author:猿說編程
@Blog(個(gè)人博客地址): www.codersrc.com
@File:Python 線程創(chuàng)建和傳參.py
@Time:2021/04/24 08:00
@Motto:不積跬步無以至千里,不積小流無以成江海赞季,程序人生的精彩需要堅(jiān)持不懈地積累!
"""
# 導(dǎo)入線程threading模塊
import threading
# 導(dǎo)入內(nèi)置模塊time
import time
def wash_clothes(*args,**kargcs):
time.sleep(2)
print("wash_clothes:",args)
time.sleep(2)
print("wash_clothes:", kargcs)
def clean_room(*args,**kargcs):
time.sleep(2)
print("clean_room:",args)
time.sleep(2)
print("clean_room:", kargcs)
if __name__ == "__main__":
# args 傳遞元組管跺,可以同時(shí)傳遞多個(gè)數(shù)據(jù)
# kwargs 傳遞字典泻云,可以同時(shí)傳遞多個(gè)鍵值對
t1 = threading.Thread(target=wash_clothes,args=(1,"猿說python"),kwargs={"a":1,"b":False})
t2 = threading.Thread(target=clean_room,args=(2,False),kwargs={"c":0.2,"d":False})
# setDaemon(True)意味著主線程退出卸夕,不管子線程執(zhí)行到哪一步,子線程自動結(jié)束
# t1.setDaemon(True)
# t2.setDaemon(True)
t1.start()
t2.start()
print("threading.enumerate():",threading.enumerate())
print("threading.activeCount():", threading.activeCount())
print("t1.isAlive():",t1.isAlive())
print("t1.getName():", t1.getName())
print("t2.isAlive():", t2.isAlive())
t2.setName("my_custom_thread_2")
print("t2.getName():", t2.getName())
'''
輸出結(jié)果:
threading.enumerate(): [<_MainThread(MainThread, started 18388)>, <Thread(Thread-1, started 16740)>, <Thread(Thread-2, started 17888)>]
threading.activeCount(): 3
t1.isAlive(): True
t1.getName(): Thread-1
t2.isAlive(): True
t2.getName(): my_custom_thread_2
clean_room: (2, False)
wash_clothes: (1, '猿說python')
wash_clothes: {'a': 1, 'b': False}
clean_room: {'c': 0.2, 'd': False}
'''
六.Python 線程重點(diǎn)總結(jié)
1.默認(rèn)主線程會等待所有子線程結(jié)束之后才會結(jié)束,主線程結(jié)束意味著程序退出;如果 setDaemon 設(shè)置為 True ,主線程則不會等待子線程晕讲,主線程結(jié)束,子線程自動結(jié)束摹量;
2.threading 模塊除了以上常用函數(shù),還有互斥鎖 Lock / 事件 Event / 信號量 Condition / 隊(duì)列 Queue 等,由于篇幅有限山害,后面文章再一一講解!!
七.猜你喜歡
- Python for 循環(huán)
- Python 字符串
- Python 列表 list
- Python 元組 tuple
- Python 字典 dict
- Python 條件推導(dǎo)式
- Python 列表推導(dǎo)式
- Python 字典推導(dǎo)式
- Python 函數(shù)聲明和調(diào)用
- Python 不定長參數(shù) *argc/**kargcs
- Python 匿名函數(shù) lambda
- Python return 邏輯判斷表達(dá)式
- Python 字符串/列表/元組/字典之間的相互轉(zhuǎn)換
- Python 局部變量和全局變量
- Python type 函數(shù)和 isinstance 函數(shù)區(qū)別
- Python is 和 == 區(qū)別
- Python 可變數(shù)據(jù)類型和不可變數(shù)據(jù)類型
- Python 淺拷貝和深拷貝
未經(jīng)允許不得轉(zhuǎn)載:猿說編程 ? Python 線程創(chuàng)建和傳參
本文由博客 - 猿說編程 猿說編程 發(fā)布!