關(guān)于threading模塊

從網(wǎng)上找到了兩篇言簡意賅的文章
https://www.cnblogs.com/fnng/p/3670789.html
http://blog.csdn.net/zhangzheng0413/article/details/41728869/
稍微修改總結(jié)一下

首先得先明白多個子線程之間是如何同時運行的(python2)

第一種情況:

import threading
from time import ctime,sleep

def music(func):
    for i in range(2):
        print "I was listening to %s. %s" %(func,ctime())
        sleep(1)

def move(func):
    for i in range(2):
        print "I was at the %s! %s" %(func,ctime())
        sleep(5)



if __name__ == '__main__':
    music(u'愛情買賣')
    move(u'阿凡達')

    print "all over %s" %ctime()

運行結(jié)果為下

>>> 
I was listening to 愛情買賣. Thu Apr 17 11:48:59 2014
I was listening to 愛情買賣. Thu Apr 17 11:49:00 2014
I was at the 阿凡達! Thu Apr 17 11:49:01 2014
I was at the 阿凡達! Thu Apr 17 11:49:06 2014
all over Thu Apr 17 11:49:11 2014

這種情況比較簡單,我們還沒有啟動子線程,所以輸出語句通過time.sleep方法按順序執(zhí)行下來


第二種情況我們啟用多線程:

import threading
from time import ctime,sleep


def music(func):
    for i in range(2):
        print "I was listening to %s. %s" %(func,ctime())
        sleep(1)

def move(func):
    for i in range(2):
        print "I was at the %s! %s" %(func,ctime())
        sleep(5)

threads = []
t1 = threading.Thread(target=music,args=(u'愛情買賣',))
threads.append(t1)
t2 = threading.Thread(target=move,args=(u'阿凡達',))
threads.append(t2)

if __name__ == '__main__':
    for t in threads:
        t.setDaemon(True)
        t.start()

    print "all over %s" %ctime()

利用threading.Thread(target=xxxx)創(chuàng)建線程,這里我們創(chuàng)建了兩個線程,并將他們添加到threads這個list中,這種情況執(zhí)行的關(guān)鍵在于for循環(huán)語句內(nèi),setDaemon()為守護線程方法,在文章頭的其中一篇內(nèi)有提到,我們以當前這個情況為例子。
先是for循環(huán),通過setDaemon()我們在主線程中調(diào)用了t1.setDaemon(),注意for循環(huán)中t1.setDaemon()和t2.setDaemon()設(shè)置的主線程都為當前py文件,當設(shè)置為True時,如果我們的主線程(也就是當前的py文件)結(jié)束了,那么不管t1,t2兩個子線程是否完成,都一并和主線程一起退出。所以輸出結(jié)果如下

>>> 
I was listening to 愛情買賣. Thu Apr 17 12:51:45 2014 I was at the 阿凡達! Thu Apr 17 12:51:45 2014  all over Thu Apr 17 12:51:45 2014

所以當主線程執(zhí)行完畢后,子線程也終止,也就不再輸出,如果我們改True為False時,則輸出結(jié)果如下

I was listening to 愛情買賣. Fri Nov 10 20:54:20 2017
I was at the 阿凡達! Fri Nov 10 20:54:20 2017
all over Fri Nov 10 20:54:20 2017
I was listening to 愛情買賣. Fri Nov 10 20:54:21 2017
I was at the 阿凡達! Fri Nov 10 20:54:25 2017
[Finished in 10.1s]

因為改為了False,所以即使主線程結(jié)束了,子線程 也會接著運行,這里特別注意一點,“all over ...” 輸出的位置為結(jié)果中間,也就是說主線程并沒有阻塞!這也是下面介紹的join()方法與setDaemon(False)最大的不同,join()方法會阻塞主線程。


第三種情況(加入join()方法):

import threading
from time import ctime,sleep


def music(func):
    for i in range(2):
        print "I was listening to %s. %s" %(func,ctime())
        sleep(1)

def move(func):
    for i in range(2):
        print "I was at the %s! %s" %(func,ctime())
        sleep(5)

threads = []
t1 = threading.Thread(target=music,args=(u'愛情買賣',))
threads.append(t1)
t2 = threading.Thread(target=move,args=(u'阿凡達',))
threads.append(t2)

if __name__ == '__main__':
    for t in threads:
        t.start()
    for t in threads:
        t.join()
    print "all over %s" %ctime()

當主線程迅速的執(zhí)行完第一個for循環(huán)時,啟動了兩個線程,于是主線程接著運行,到了第二個for循環(huán),當執(zhí)行t1.join()時,主線程被阻塞了,所以必須等待t1線程執(zhí)行完畢才能接著下一步,接著再執(zhí)行t2.join()同理。因此執(zhí)行結(jié)果會如下

>>> 
I was listening to 愛情買賣. Thu Apr 17 13:04:11 2014  I was at the 阿凡達! Thu Apr 17 13:04:11 2014

I was listening to 愛情買賣. Thu Apr 17 13:04:12 2014
I was at the 阿凡達! Thu Apr 17 13:04:16 2014
all over Thu Apr 17 13:04:21 2014

如果我們向之前一樣往執(zhí)行語句里面加入setDaemon(True)

if __name__ == '__main__':
    for t in threads:
        t.setDaemon(True)
        t.start()
    for t in threads:
        t.join()
    print "all over %s" %ctime()

因為t.join()阻塞了主線程,所以主線程不可能跑的比子線程快,所以這里的setDaemon(True)也就可有可無了,執(zhí)行結(jié)果也會想同

I was listening to 愛情買賣. Thu Apr 17 13:11:27 2014I was at the 阿凡達! Thu Apr 17 13:11:27 2014

I was listening to 愛情買賣. Thu Apr 17 13:11:31 2014
I was at the 阿凡達! Thu Apr 17 13:11:32 2014
all over Thu Apr 17 13:11:37 2014

關(guān)鍵在于注意理解t.join()和setDaemon(False)的區(qū)別,以及通過輸出語句的時間對比,體會子進程的執(zhí)行順序。如果理解困難可以先由單個子線程開始,后面再嘗試添加for循環(huán)和多個子線程,同時理解。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容