線程(Thread)基本用法

一.線程的調用

1.無參

def run_01():
    for i in range(6, 10):
        print("test01", i)
        time.sleep(1)


th_01 = threading.Thread(target=run_01)  # 創建線程
th_01.start()  # 啟動線程

for i in range(0, 5):
    print("main", i)
    time.sleep(1)

threading中最主要的類就是Thread,我們可通過實例化Thread類來創建一個子線程,target參數為運行的事件。

start()方法為啟動線程,線程運行結束或報異常時自動會結束線程。

程序默認在主線程上運行,不做任何操作的話,子線程和主線程是同步進行的。

2.有參

def run_01(a):
    for i in range(6, 10):
        print("test01", i)
        time.sleep(1)


th_01 = threading.Thread(target=run_01, args=("test",))  # 創建線程
th_01.start()  # 啟動線程

若運行的事件有參數時,我們可通過args傳入一個元組入參,也可通過kwargs傳入字典類型。

def run_01(a):
    for i in range(6, 10):
        print("test01", i)
        time.sleep(1)


th_01 = threading.Thread(target=run_01, kwargs={"a": "test"})  # 創建線程
th_01.start()  # 啟動線程

key值要與參數值保持一致。

3.多參

def run_01(a, b):
    for i in range(6, 10):
        print("test01", i)
        time.sleep(1)


th_01 = threading.Thread(target=run_01, args=(1, 2))  # 創建線程
# or
# th_01 = threading.Thread(target=run_01, kwargs={"a": "test", "b": 1})  # 創建線程
th_01.start()  # 啟動線程

和單個入參差不多,多傳入一個參數即可。

二.設置線程名稱,獲取線程狀態

1.子線程名稱默認是Thread-1,Thread-2…..,我們可通過Thread類中name屬性設置線程名,

def run():
    for i in range(0, 5):
        print(i)


thread = threading.Thread(target=run, name='test')  # name設置線程名
print(thread.name, thread.getName())  # name,getname()方法獲取線程名

通過name屬性和getName()方法獲取線程名。修改/設備線程名也可通過setName()方法設置。

thread = threading.Thread(target=run, name='test')  # name設置線程名
thread.setName("updateThreadName")
print(thread.name, thread.getName())  # name,getName()方法獲取線程名

2.is_alive()為獲取線程當前的運行狀態

def run():
    for i in range(0, 5):
        print(i)


thread = threading.Thread(target=run, name='test')  # name設置線程名
thread.start()
bol = thread.is_alive()  # 為true時表示正在運行,為false時停止運行
print(bol)

三.主/子線程執行順序

1.默認情況下主/子線程會同時執行,主線程會等待子線程結束後再結束。

def run():
    for i in range(0, 5):
        print("thread", i)
        time.sleep(2)


if __name__ == '__main__':
    thread = threading.Thread(target=run)
    thread.start()
    for i in range(5, 10):
        print("main", i)
        time.sleep(1)

2.Thread類中有個daemon屬性可控制執行結果

if __name__ == '__main__':
    thread = threading.Thread(target=run,daemon=True)
    thread.start()
    for i in range(5, 10):
        print("main", i)
        time.sleep(1)

創建子線程時我們將daemon設置為True,可以看出主線程結束後子線程也會結束運行,

不會等待子線程結束後再結束。也可通過setDaemon()方法設置。

if __name__ == '__main__':
    thread = threading.Thread(target=run)
    thread.setDaemon(True)
    thread.start()
    for i in range(5, 10):
        print("main", i)
        time.sleep(1)

四.join()用法

1.join()為堵塞主線程執行,優先執行子線程,等子線程執行完後再去執行主線程。

def run():
    for i in range(0, 5):
        print("thread1", i)
        time.sleep(1)


def run2():
    for i in range(0, 5):
        print("thread2", i)
        time.sleep(1)


if __name__ == '__main__':
    thread = threading.Thread(target=run)
    thread2 = threading.Thread(target=run2)
    thread.start()
    thread.join()  # 開始堵塞主線程,只執行thread線程
    thread2.start()

    for i in range(5, 10):
        print("main", i)
        time.sleep(1)

2.join(timeout=None)中timeout參數

timeout默認為None,可傳遞秒數,設置堵塞主線程的時間,timeout秒後不管子線程有沒有運行完都會執行主線程。

thread.join(timeout=2.0)

五.Event()方法的使用

我們都知道一個進程有多個線程,多個線程之間的資源是共享的,那麼如果多個線程去修改同

一個資源數據,就會出現數據錯亂的情況。Event類可以去堵塞線程的運行,我們先來看下Event()的幾個方法。

1.實例化Event()類

event = threading.Event()

Event()中有個_flag的私有屬性,默認為false,表示堵塞

2.wait()調用後表示開始堵塞

event.wait(timeout=2.0)  # 調用該方法後,該線程會被堵塞,timeout為堵塞時間

3.set()方法設置flag為true,表示結束堵塞

event.set()  # 設置self._flag = True

4.清除設置,flag值恢復false,繼續堵塞

event.clear()  # self._flag = False

5.is_set()查看flag的值

print(event.is_set())  # 查看當前_flag的值

6.實例

import threading
import time


def run(event):
    print("當前flag的值", event.is_set())
    event.wait()  # 開始堵塞
    for i in range(1, 6):
        print(i)
        time.sleep(1)
        if event.is_set() == False:
            break


event = threading.Event()  # self._flag = False
thread = threading.Thread(target=run, args=(event,))
thread.start()
print("\n開始堵塞2s")
time.sleep(2)
event.set()  # 設置self._flag = True
print("結束堵塞,運行2s")
time.sleep(2)
print("結束運行,跳出for循環")
event.clear()  # self._flag = False

解析:

上述中,子線程執行到event.wait()時就開始進行堵塞,主線程等待2s後調用set()方法使子線程繼續運行,

子線程循環兩次後主線程調用clear()設置flag值為false,子線程if判斷跳出循環,運行結束。

 

 

 

 

 

 

 

 

文章來源://www.cnblogs.com/lihongtaoya/ ,請勿轉載
Tags: