一、Python線程為什么搞個(gè)setDaemon
當(dāng)啟動(dòng)一個(gè)線程時(shí)設(shè)置thread.setDaemon(True),則該線程為守護(hù)線程(也可以稱為后臺(tái)線程)。表示該線程是不重要的,進(jìn)程退出時(shí)不需要等待這個(gè)線程執(zhí)行完成。這樣做的意義在于:避免子線程無限死循環(huán),導(dǎo)致退不出程序,也就是避免了孤兒進(jìn)程的出現(xiàn)。
當(dāng)不設(shè)置或者thread.setDaemon(False)時(shí),主進(jìn)程執(zhí)行結(jié)束時(shí),會(huì)等待線程結(jié)束。
應(yīng)用:如保持網(wǎng)絡(luò)連接(發(fā)送keep-alive心跳包)或者后臺(tái)監(jiān)控的線程,負(fù)責(zé)內(nèi)存管理與垃圾回收(實(shí)際上JVM就是這樣做的),這些線程與實(shí)際提供應(yīng)用服務(wù)的線程有了邏輯上的”前/后”的概念,而如果主線程已經(jīng)退出,那么這些后臺(tái)線程也沒有存在的必要。
如果沒有這一機(jī)制,那么我們?cè)谥骶€程完成之后,還必須逐個(gè)地檢查后臺(tái)線程,然后在主線程退出之前,逐個(gè)地關(guān)閉它們. 有了前后線程的區(qū)分, 我們只需要負(fù)責(zé)管理前臺(tái)線程, 完成主要的邏輯處理之后退出即可。
當(dāng)子線程不設(shè)置時(shí),主進(jìn)程結(jié)束后,子線程會(huì)繼續(xù)執(zhí)行完后,程序結(jié)束。
import time
from hashlib import md5
from threading import Thread
def pmd(md):
?? ?time.sleep(3) #使用sleep使得該線程比主線程晚結(jié)束
??? print(“backend recording:”,md)
def giveures(s):
??? md = md5(s.encode(‘utf-8’))
??? res = md.digest()
??? t = Thread(target=pmd,args=(s,))
??? #t.setDaemon(True) 默認(rèn)情況:t.setDaemon(False)
??? t.start()
??? return res
s = ‘chrisyang’
res = giveures(s)
print(res)
當(dāng)設(shè)置時(shí),主進(jìn)程不會(huì)等待子線程,當(dāng)主線程結(jié)束,子線程就會(huì)被強(qiáng)制停止運(yùn)行并回收。
import time
from hashlib import md5
from threading import Thread
def pmd(md):
??? time.sleep(3) #使用sleep使得該線程比主線程晚結(jié)束
??? print(“backend recording:”,md)
def giveures(s):
??? md = md5(s.encode(‘utf-8’))
??? res = md.digest()
??? t = Thread(target=pmd,args=(s,))
??? t.setDaemon(True)
??? t.start()
??? return res
s = ‘chrisyang’
res = giveures(s)
print(res)
延伸閱讀:
二、異步消息隊(duì)列
說道消息隊(duì)列,你肯定會(huì)想到Kafka、Rabbitmq等消息中間件,這些專業(yè)的消息中間件提供了很多功能特性,當(dāng)然他的部署使用維護(hù)都是比較麻煩的。如果你對(duì)消息隊(duì)列沒那么高要求,想要輕量級(jí)的,使用Redis就沒錯(cuò)啦。
Redis通過list數(shù)據(jù)結(jié)構(gòu)來實(shí)現(xiàn)消息隊(duì)列.主要使用到如下命令:
lpush和rpush入隊(duì)列l(wèi)pop和rpop出隊(duì)列blpop和brpop阻塞式出隊(duì)列