python 線程建立和傳參(28)

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

修煉

 

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

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

多線程:把衣服放到洗衣機而且30分鐘後自動結束,而後馬上開始打掃房間60分鐘,累計耗時:60分鐘;微信

因而可知,完成一樣的事情,單線程是一件事情作完以後繼續下一件事情,而多線程能夠同時執行多件事情,因此多線程比單線程效率更高!多線程

 

 

一.線程解釋

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

 

 

二.線程建立和啓動

1.導入線程模塊


1函數

2學習

# 導入線程threading模塊spa

import threading線程

 

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

調用threading模塊中的缺省函數Thread,建立並初始化線程,返回線程句柄。若是對缺省函數已經忘記的小夥伴請回到 python函數的聲明和定義中關於缺省參數部分複習一下。

1

2

# 建立並初始化線程,返回線程句柄

t = threading.Thread(target=函數名)

 

3.啓動線程

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

1

2

# 啓動線程

t.start()

 

 

綜合上面三點,下面使用代碼對python線程thread作詳細講解:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

# !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()

輸出結果:

1

2

3

4

洗衣服開始...

打掃房間開始...

洗衣服完成...

打掃房間完成...

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

  • 一:洗衣服開始和打掃房間開始幾乎同時開始,兩個事件同時執行.

  • 二:程序中止5秒;

  • 三:洗衣服和打掃房間幾乎同時完成

 

固然你也能夠按照之前的學習的內容,先調用wash_clothes函數,在調用clean_room函數,一樣能輸出內容,而耗時倒是10秒左右,示例代碼以下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

# 導入內置模塊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()

輸出結果:

1

2

3

4

洗衣服開始...

洗衣服完成...

打掃房間開始...

打掃房間完成...

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

  • 一:洗衣服開始;

  • 二:程序中止了5秒;

  • 三:洗衣服完成,打掃房間開始

  • 四:程序中止5秒;

  • 五:打掃房間結束,程序結束;

因而可知:多線程能夠同時運行多個任務,效率遠比單線程更高!

 

 

 

三.線程傳參

在上面的demo中,咱們並無爲線程傳遞參數,若是在線程中須要傳遞參數怎麼辦呢?

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

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.

 

    """

示例代碼以下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

# 導入線程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()以前

 

簡單的示例代碼:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

# 導入線程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())

輸出結果:

1

2

3

4

5

6

7

8

9

10

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線程建立和傳參

相關文章
相關標籤/搜索