python 線程創建和傳參(28)

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

修煉

 

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

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

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

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

 

 

一.線程解釋

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

 

 

二.線程創建和啓動

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(個人博客地址): shuopython.com
@WeChat Official Account(微信公衆號):猿說python
@Github:www.github.com
 
@File:python_thread.py
@Time:2019/10/16 21:02
 
@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秒左右,示例代碼如下:

# 導入內置模塊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秒;
  •     第五步:打掃房間結束,程序結束;

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

 

 

 

三.線程傳參

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

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

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

示例代碼如下:

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

 

 

 

 

四.線程結束

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

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

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

五.相關函數介紹

    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()之前;

 

    簡單的示例代碼:

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

 

 

 

六.重點總結

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

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

 

 

猜你喜歡:

    1.python模塊

    2.python匿名函數

    3.python不定長參數 *argc,**kargcs

    4.python異常處理

 

     轉載請註明:猿說Python » python線程創建和傳參

 

技術交流、商務合作請直接聯繫博主
掃碼或搜索:猿說python
python教程公衆號
猿說python
微信公衆號 掃一掃關注
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章