python線程

線程模塊

Python標準庫提供了兩個線程模塊:_threadthreading_thread 提供了低級別的、原始的線程以及一個簡單的互斥鎖,相比threading模塊的功能還是比較有限的。threading模塊是_thread模塊的替代,在實際開發中,絕大多數情況下還是使用高級模塊threading

創建thread對象語法如下:

import threading

threading.Thread(target=None, name=None, args=())

主要參數說明:

target是函數名字,需要調用的函數。
name設置線程名字。
args是函數需要的參數,以元祖的形式傳入。

主要方法說明:

run(): 用以表示線程活動的方法。
start(): 啟動線程活動。
join(): 等待至線程中止。
isAlive(): 返回線程是否活動的。
getName(): 返回線程名。
setName(): 設置線程名。

函數式創建線程

創建線程的時候,只需要傳入一個執行函數和函數的參數即可。下面的例子使用thread類來產生2個子線程,然后啟動2個子線程并等待其結束,

#!/usr/bin/python
# -*- coding: UTF-8 -*-


import threading
import time,random,math
 

def print_num(idx):
    for num in range(idx):
        print("{0}\tnum={1}".format(threading.current_thread().getName(), num))
        delay = math.ceil(random.random() * 2)
        time.sleep(delay)
 
if __name__ == '__main__':
    th1 = threading.Thread(target=print_num, args=(2,), name="test1")
    th2 = threading.Thread(target=print_num, args=(3,), name="test2")

    th1.start()
    th2.start()

    th1.join()
    th2.join()
    print("{0} over".format(threading.current_thread().getName()))

運行結果如下:

$ python thread1.py 
test1    num=0
test2    num=0
test1    num=1
test2    num=1
test2    num=2
MainThread over

運行腳本默認會啟動一個線程,把該線程稱為主線程,主線程又啟動新的線程。Pythonthreading模塊有個current_thread()函數,它將返回當前線程的實例,可以獲得運行線程名字,代碼如下:

threading.current_thread().getName()

啟動一個線程就是把一個函數和參數傳入并創建Thread實例,然后調用start()開始執行:

th1 = threading.Thread(target=print_num, args=(2,), name="test1" )
th1.start()

從返回結果可以看出主線程的名字叫MainThread,子線程的名字在創建時指定。如果沒有給線程起名字,Python就自動給線程命名為Thread-1Thread-2等等。

創建線程類

通過繼承Thread類,并重寫Thread類的run()方法,在run()方法中定義具體要執行的任務。在Thread類中,提供了一個start()方法用于啟動新線程,線程啟動后會自動調用run()方法。

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import threading
import time,random,math


class MutliThread(threading.Thread):
    def __init__(self, threadName, num):
        threading.Thread.__init__(self)
        self.name     = threadName
        self.num     = num
 
    def run(self):
        for i in range(self.num):
            print("{0} i={1}".format(threading.current_thread().getName(), i))
            delay = math.ceil(random.random() * 2)
            time.sleep(delay)

if __name__ == '__main__':
    thr1 = MutliThread("test1", 3)
    thr2 = MutliThread("test2", 2)

    thr1.start()
    thr2.start()

    thr1.join()
    thr2.join()
    print("{0} over".format(threading.current_thread().getName()))

運行結果如下:

$ python thread2.py 
test1 i=0
test2 i=0
test1 i=1
test2 i=1
test1 i=2
MainThread over

從返回結果可以看出,通過創建Thread類來產生2個線程對象thr1thr2,重寫Thread類的run()函數,把業務邏輯放入其中,通過調用線程對象的start()方法啟動線程。通過調用線程對象的join()函數,等待該線程完成。

守護線程

在線程模塊中,使用子線程對象用到join()函數,主線程需要依賴子線程執行完畢后才繼續執行。如果不使用join()函數,主線程和子線程是并行運行的,沒有依賴關系。

在多線程開發中,如果子線程設定為守護線程,守護線程會等待主線程運行完畢后被銷毀。一個主線程可以設置多個守護線程,守護線程運行的前提是主線程必須存在,如果主線程不存在了,守護線程會被銷毀。

以下例子創建了1個主線程和3個子線程,讓主線程和子線程并行執行,代碼如下:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import threading, time


def run(taskName):
    print("task:", taskName)
    time.sleep(2)
    print("{0} over".format(taskName))
 
if __name__ == '__main__':
    start_time = time.time()
    for i in range(3):
        thr = threading.Thread(target=run, args=("task-{0}".format(i),))
        thr.start()

    print("{0} over,thread_num={1}".format(threading.current_thread().getName(), threading.active_count()))
    print("cost time:", time.time() - start_time)

運行結果如下:

$ python thread3.py 
('task:', 'task-0')
('task:', 'task-1')
('task:', 'task-2')
MainThread over,thread_num=4
('cost time:', 0.0011091232299804688)
task-0 over
task-1 over
task-2 over

從返回結果可以看出,當前的線程個數是4,主線程執行完畢后,等待子線程執行完畢,程序才會退出。

在以上例子的基礎上,使用線程對象的setDaemon(True)函數把所有的子線程都設置為守護線程。子線程變成守護線程后,只要主線程執行完畢,程序不管子線程有沒有執行完畢,程序都會退出。

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import threading, time
 
def run(taskName):
    print("task:", taskName)
    time.sleep(2)
    print("{0} over".format(taskName))
 
if __name__ == '__main__':
    start_time = time.time()
    for i in range(3):
        thr = threading.Thread(target=run, args=("task-{0}".format(i),))
        thr.setDaemon(True)
        thr.start()

    thrName  = threading.current_thread().getName()
    thrCount = threading.active_count()

    print("{0} over,thread_num={1}".format(thrName, thrCount))
    print("cost time:", time.time() - start_time)

運行結果如下:

$ python thread4.py 
('task:', 'task-0')
('task:', 'task-1')
('task:', 'task-2')
MainThread over,thread_num=4
('cost time:', 0.0005180835723876953)

從返回結果可以看出,主線程執行完畢后,程序不會等待守護線程執行完畢就退出了。設置線程對象為守護線程,一定要在線程對象調用start()函數前設置。

你可能感興趣的

广东25选5开奖结果