Python 線程創建和傳參 - Python零基礎入門教程


目錄

零基礎 Python 學習路線推薦 : Python 學習目錄 >> Python 基礎入門

在以前的文章中雖然我們沒有介紹過線程這個概念,但是實際上前面所有代碼都是線程,只不過是單線程,代碼由上而下依次執行或者進入 main 函數執行,這樣的單線程也稱為主線程

有了單線程的話,什么又是多線程?可以這么理解:一個線程執行一個代碼塊,多個線程可以同時執行多個代碼,使用多線程能讓程序效率更高。舉個例子,你今天有兩件事需要完成,分別是洗衣服和打掃房間,分別來看看單線程和多線程如何完成:

單線程:先用洗衣機洗衣服30分鍾,等衣服洗完之后再打掃房間60分鍾,累計總耗時:90分鍾;

多線程:把衣服放到洗衣機並且30分鍾后自動結束,然后立刻開始打掃房間60分鍾,累計耗時:60分鍾;

由此可見,完成同樣的事情,單線程是一件事情做完之后繼續下一件事情,而多線程可以同時執行多件事情,所以多線程比單線程效率更高!

一.Python 線程解釋

線程是 cpu 最小調度單位,一個程序中至少有一個或者多個線程(至於進程暫時不做講解,后面文章會有詳細解釋)!在開發中使用線程可以讓程序運行效率更高,多線程類似於同時執行多個不同代碼塊。

二.Python 線程創建和啟動

1.導入線程模塊

# 導入線程threading模塊
import threading

2.創建線程並初始化線程

調用 threading 模塊中的缺省函數 Thread ,創建並初始化線程,返回線程句柄。如果對缺省函數已經忘記的小伙伴請回到 Python 函數的聲明和定義中關於缺省參數部分復習一下。

# 創建並初始化線程,返回線程句柄
t = threading.Thread(target=函數名)

3.啟動線程

通過初始化返回的線程句柄調用 start 函數,啟動線程,此時會自動執行在創建線程時 target 對應的函數內部的代碼:

# 啟動線程
t.start()

綜合上面三步,下面使用代碼對 Python 線程 thread 做詳細講解:

# !usr/bin/env python
# -*- coding:utf-8 _*-
"""
@Author:猿說編程
@Blog(個人博客地址): www.codersrc.com
@File:Python 線程創建和傳參.py
@Time:2021/04/24 08:00
@Motto:不積跬步無以至千里,不積小流無以成江海,程序人生的精彩需要堅持不懈地積累!

"""


# 導入線程threading模塊
import threading
# 導入內置模塊time
import time

def wash_clothes():
    print("洗衣服開始...")
    # sleep 5 秒,默認以秒為單位
    time.sleep(5)
    print("洗衣服完成...")

def clean_room():
    print("打掃房間開始...")
    # sleep 5 秒,默認以秒為單位
    time.sleep(5)
    print("打掃房間完成...")

if __name__ == "__main__":

    # 創建線程並初始化 -- 該線程執行wash_clothes中的代碼
    t1 = threading.Thread(target=wash_clothes)
     # 創建線程並初始化 -- 該線程執行clean_room中的代碼
    t2 = threading.Thread(target=clean_room)

    t1.start()
    t2.start()


'''
輸出結果:

洗衣服開始...
打掃房間開始...
洗衣服完成...
打掃房間完成...
'''

運行程序可以發現程序從運行開始到結束,一共耗時 5 秒時間!注意觀察輸出日志:

  • 第一步:洗衣服開始和打掃房間開始幾乎同時開始,兩個事件同時執行.
  • 第二步:程序停止 5 秒;
  • 第三步:洗衣服和打掃房間幾乎同時完成

當然你也可以按照以前的學習的內容,先調用 wash_clothes 函數,在調用 clean_room 函數,同樣能輸出內容,而耗時卻是 10 秒左右,示例代碼如下:

# !usr/bin/env python
# -*- coding:utf-8 _*-
"""
@Author:猿說編程
@Blog(個人博客地址): www.codersrc.com
@File:Python 線程創建和傳參.py
@Time:2021/04/24 08:00
@Motto:不積跬步無以至千里,不積小流無以成江海,程序人生的精彩需要堅持不懈地積累!

"""


# 導入內置模塊time
import time

def wash_clothes():
    print("洗衣服開始...")
    # sleep 5 秒,默認以秒為單位
    time.sleep(5)
    print("洗衣服完成...")

def clean_room():
    print("打掃房間開始...")
    # sleep 5 秒,默認以秒為單位
    time.sleep(5)
    print("打掃房間完成...")

if __name__ == "__main__":

    wash_clothes()
    clean_room()


'''
輸出結果:

洗衣服開始...
洗衣服完成...
打掃房間開始...
打掃房間完成...

'''

運行程序可以發現程序從運行開始到結束,一共耗時 10 秒時間!注意觀察輸出日志:

  • 第一步:洗衣服開始;
  • 第二步:程序停止了 5 秒;
  • 第三步:洗衣服完成,打掃房間開始
  • 第四步:程序停止 5 秒;
  • 第五步:打掃房間結束,程序結束;

由此可見:多線程可以同時運行多個任務,效率遠比單線程更高!

三.Python 線程傳參

在上面的例子中,我們並沒有為線程傳遞參數,如果在線程中需要傳遞參數怎么辦呢?

threading.Thread 函數中有兩個缺省參數 args 和 kwargs ,args 是元組類型,kwargs 是字典類型,缺省值默認為空,除此之外,其實還可以設置線程的名字等,其函數聲明如下:

(ps:如果對缺省函數已經忘記的小伙伴請回到 Python 函數的聲明和定義中關於缺省參數部分復習一下)

# !usr/bin/env python
# -*- coding:utf-8 _*-
"""
@Author:猿說編程
@Blog(個人博客地址): www.codersrc.com
@File:Python 線程創建和傳參.py
@Time:2021/04/24 08:00
@Motto:不積跬步無以至千里,不積小流無以成江海,程序人生的精彩需要堅持不懈地積累!

"""

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(個人博客地址): www.codersrc.com
@File:Python 線程創建和傳參.py
@Time:2021/04/24 08:00
@Motto:不積跬步無以至千里,不積小流無以成江海,程序人生的精彩需要堅持不懈地積累!

"""

# 導入線程threading模塊
import threading
# 導入內置模塊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 傳遞元組,可以同時傳遞多個數據
        # kwargs 傳遞字典,可以同時傳遞多個鍵值對
    t1 = threading.Thread(target=wash_clothes,args=(1,"猿說python"),kwargs={"a":1,"b":False})

        # args 傳遞元組,可以同時傳遞多個數據
        # kwargs 傳遞字典,可以同時傳遞多個鍵值對
    t2 = threading.Thread(target=clean_room,args=(2,False),kwargs={"c":0.2,"d":False})

    t1.start()
    t2.start()

四.Python 線程結束

值得思考的是:在上面這份代碼中一共有幾個線程呢?並非兩個,一共是三個線程:

  • 線程一:__name__ == “__main__” 作為主線程;
  • 線程二:t1 作為子線程;
  • 線程三:t2 作為子線程;

注意:主程序會等待所有子程序結束之后才會結束!

五.Python 線程相關函數介紹

  • 1.threading.Thread — 創建線程並初始化線程,可以為線程傳遞參數 ;
  • 2.threading.enumerate — 返回一個包含正在運行的線程的 list;
  • 3.threading.activeCount — 返回正在運行的線程數量,與 len(threading.enumerate)有相同的結果;
  • 4.Thread.start — 啟動線程 ;
  • 5.Thread.join — 阻塞函數,一直等到線程結束為止 ;
  • 6.Thread.isAlive — 返回線程是否活動的;
  • 7.Thread.getName — 返回線程名;
  • 8.Thread.setName — 設置線程名;
  • 9.Thread.setDaemon — 設置為后台線程,這里默認是 False,設置為 True 之后則主線程不會再等待子線程結束才結束,而是主線程結束意味程序退出,子線程也立即結束,注意調用時必須設置在 start 之前

簡單的示例代碼:

# !usr/bin/env python
# -*- coding:utf-8 _*-
"""
@Author:猿說編程
@Blog(個人博客地址): www.codersrc.com
@File:Python 線程創建和傳參.py
@Time:2021/04/24 08:00
@Motto:不積跬步無以至千里,不積小流無以成江海,程序人生的精彩需要堅持不懈地積累!

"""

# 導入線程threading模塊
import threading
# 導入內置模塊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 傳遞元組,可以同時傳遞多個數據
        # kwargs 傳遞字典,可以同時傳遞多個鍵值對
    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)意味着主線程退出,不管子線程執行到哪一步,子線程自動結束
    # 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())


'''
輸出結果:

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 線程重點總結

1.默認主線程會等待所有子線程結束之后才會結束,主線程結束意味着程序退出;如果 setDaemon 設置為 True ,主線程則不會等待子線程,主線程結束,子線程自動結束;

2.threading 模塊除了以上常用函數,還有互斥鎖 Lock / 事件 Event / 信號量 Condition / 隊列 Queue 等,由於篇幅有限,后面文章再一一講解!!

七.猜你喜歡

  1. Python for 循環
  2. Python 字符串
  3. Python 列表 list
  4. Python 元組 tuple
  5. Python 字典 dict
  6. Python 條件推導式
  7. Python 列表推導式
  8. Python 字典推導式
  9. Python 函數聲明和調用
  10. Python 不定長參數 *argc/**kargcs
  11. Python 匿名函數 lambda
  12. Python return 邏輯判斷表達式
  13. Python 字符串/列表/元組/字典之間的相互轉換
  14. Python 局部變量和全局變量
  15. Python type 函數和 isinstance 函數區別
  16. Python is 和 == 區別
  17. Python 可變數據類型和不可變數據類型
  18. Python 淺拷貝和深拷貝

未經允許不得轉載:猿說編程 » Python 線程創建和傳參

本文由博客 - 猿說編程 猿說編程 發布!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM