詳解Python 多線程 Timer定時(shí)器/延遲執(zhí)行、Event事件
Timer繼承子Thread類,是Thread的子類,也是線程類,具有線程的能力和特征。這個(gè)類用來定義多久執(zhí)行一個(gè)函數(shù)。
它的實(shí)例是能夠延遲執(zhí)行目標(biāo)函數(shù)的線程,在真正執(zhí)行目標(biāo)函數(shù)之前,都可以cancel它。
Timer源碼:
class Timer(Thread):
def __init__(self, interval, function, args=None, kwargs=None):
Thread.__init__(self)
self.interval = interval
self.function = function
self.args = args if args is not None else []
self.kwargs = kwargs if kwargs is not None else {}
self.finished = Event()
def cancel(self):
"""Stop the timer if it hasn't finished yet."""
self.finished.set()
def run(self):
self.finished.wait(self.interval)
if not self.finished.is_set():
self.function(*self.args, **self.kwargs)
self.finished.set()
Timer類使用方法與Thread定義子線程一樣,interval傳入間隔時(shí)間,function傳入線程執(zhí)行的函數(shù),args和kwargs傳入函數(shù)的參數(shù)。
提前cancel:
import threading
import time
def add(x,y):
print(x+y)
t = threading.Timer(10,add,args=(4,5))
t.start()
time.sleep(2)
t.cancel()
print("===end===")
運(yùn)行結(jié)果:
===end===
start方法執(zhí)行之后,Timer對(duì)象會(huì)處于等待狀態(tài),等待10秒之后會(huì)執(zhí)行add函數(shù)。同時(shí),在執(zhí)行add函數(shù)之前的等待階段,主線程使用了子線程的cancel方法,就會(huì)跳過執(zhí)行函數(shù)結(jié)束。
使用event 事件實(shí)現(xiàn)Timer計(jì)時(shí)器:
import threading import logging import time logging.basicConfig(level=logging.INFO) # class MyTimer(threading.Thread): class MyTimer: def __init__(self,interval,fn,args=None): self.interval = interval self.fn = fn self.args = args self.event = threading.Event() def start(self): threading.Thread(target=self.__do).start() def cancel(self): self.event.set() def __do(self): self.event.wait(self.interval) if not self.event.is_set(): self.fn(*self.args) def add(x,y): logging.warning(x+y) t = MyTimer(5,add,(4,5)) t.start() # time.sleep(2) # t.cancel()
運(yùn)行結(jié)果:
WARNING:root:9
Event事件,是線程間通信機(jī)制中最簡(jiǎn)單的實(shí)現(xiàn),使用一個(gè)內(nèi)部的標(biāo)記flag,通過flag的True或False的變化來進(jìn)行操作。
Event源碼:
class Event:
def __init__(self):
self._cond = Condition(Lock())
self._flag = False
def _reset_internal_locks(self):
self._cond.__init__(Lock())
def is_set(self):
return self._flag
isSet = is_set
def set(self):
with self._cond:
self._flag = True
self._cond.notify_all()
def clear(self):
with self._cond:
self._flag = False
def wait(self, timeout=None):
with self._cond:
signaled = self._flag
if not signaled:
signaled = self._cond.wait(timeout)
return signaled
Event 方法:
•set() flag設(shè)置為True
•clear() flag設(shè)置為False
•is_set() flag是否為True,返回布爾值
•wait(timeout=None) 設(shè)置等待flag變?yōu)門rue的時(shí)長(zhǎng),None為無(wú)限等待。等到了返回True,未等到超時(shí)了就返回False。
舉例:
老板雇傭了一個(gè)工人,讓他生產(chǎn)杯子,老板一直等著工人,直到生產(chǎn)了10個(gè)杯子。
import threading
import logging
import time
logging.basicConfig(level=logging.INFO)
cups = []
event = threading.Event()#event對(duì)象
def boss(e:threading.Event):
if e.wait(30):#最多等待30秒
logging.info('Good job.')
def worker(n,e:threading.Event):
while True:
time.sleep(0.5)
cups.append(1)
logging.info('make 1')
if len(cups) >=n:
logging.info('I finished my job. {}'.format(len(cups)))
e.set()#flag設(shè)置為True
break
b = threading.Thread(target=boss,name='boos',args=(event,))
w = threading.Thread(target=worker,args=(10,event))
w.start()
b.start()
運(yùn)行結(jié)果:
INFO:root:make 1
INFO:root:make 1
INFO:root:make 1
INFO:root:make 1
INFO:root:make 1
INFO:root:make 1
INFO:root:make 1
INFO:root:make 1
INFO:root:make 1
INFO:root:make 1
INFO:root:I finished my job. 10
INFO:root:Good job.
老板和工人使用同一個(gè)Event對(duì)象的標(biāo)記flag。
老板wait()設(shè)置為最多等待30秒,等待flag變?yōu)門rue,工人在做夠10杯子時(shí),將flag設(shè)置為True,工人必須在30秒之內(nèi)沒有做好杯子。
wait的使用:
import threading
import logging
logging.basicConfig(level=logging.INFO)
def do(event:threading.Event,interval:int):
while not event.wait(interval): # not event.wait(1) = True
logging.info('To do sth.')
e = threading.Event()
t = threading.Thread(target=do,args=(e,1))
t.start()
e.wait(10) # 也可以使用time.sleep(10)
e.set()
print('Man Exit.')
運(yùn)行結(jié)果:
INFO:root:To do sth.
INFO:root:To do sth.
INFO:root:To do sth.
INFO:root:To do sth.
INFO:root:To do sth.
INFO:root:To do sth.
INFO:root:To do sth.
INFO:root:To do sth.
INFO:root:To do sth.
Man Exit.
wait與sleep的區(qū)別是:wait會(huì)主動(dòng)讓出時(shí)間片,其它線程可以被調(diào)度,而sleep會(huì)占用時(shí)間片不讓出。
小結(jié):
Timer定時(shí)器繼承自Thread類,也是線程類。它的作用是等待n秒鐘之后執(zhí)行某個(gè)目標(biāo)函數(shù),可以使用cancel提前取消。
Event事件是通過True和False維護(hù)一個(gè)flag標(biāo)記值,通過這個(gè)標(biāo)記的值來決定做某事,wait()方法可以設(shè)置最長(zhǎng)等待flag設(shè)置為Ture的時(shí)長(zhǎng),超時(shí)還未設(shè)置為True就返回False。
PS:下面看下python之定時(shí)器Timer
timer類
Timer(定時(shí)器)是Thread的派生類,用于在指定時(shí)間后調(diào)用一個(gè)方法。
構(gòu)造方法:
Timer(interval, function, args=[], kwargs={})
interval: 指定的時(shí)間
function: 要執(zhí)行的方法
args/kwargs: 方法的參數(shù)
實(shí)例方法:
Timer從Thread派生,沒有增加實(shí)例方法。
例子一:
# encoding: UTF-8 import threading def func(): print 'hello timer!' timer = threading.Timer(5, func) timer.start()
線程延遲5秒后執(zhí)行。
總結(jié)
以上所述是小編給大家介紹的詳解Python 多線程 Timer定時(shí)器/延遲執(zhí)行、Event事件,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
- Python多線程同步Lock、RLock、Semaphore、Event實(shí)例
- 分析Python感知線程狀態(tài)的解決方案之Event與信號(hào)量
- Python中使用threading.Event協(xié)調(diào)線程的運(yùn)行詳解
- python基于event實(shí)現(xiàn)線程間通信控制
- python Event事件、進(jìn)程池與線程池、協(xié)程解析
- 詳解python多線程、鎖、event事件機(jī)制的簡(jiǎn)單使用
- python多線程之事件Event的使用詳解
- Python多線程編程(八):使用Event實(shí)現(xiàn)線程間通信
- python中Event實(shí)現(xiàn)線程間同步介紹
相關(guān)文章
pytorch對(duì)梯度進(jìn)行可視化進(jìn)行梯度檢查教程
今天小編就為大家分享一篇pytorch對(duì)梯度進(jìn)行可視化進(jìn)行梯度檢查教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-02-02
Python調(diào)用Prometheus監(jiān)控?cái)?shù)據(jù)并計(jì)算
Prometheus是一套開源監(jiān)控系統(tǒng)和告警為一體,由go語(yǔ)言(golang)開發(fā),是監(jiān)控+報(bào)警+時(shí)間序列數(shù)據(jù)庫(kù)的組合。本文將介紹Python如何調(diào)用Prometheus實(shí)現(xiàn)數(shù)據(jù)的監(jiān)控與計(jì)算,需要的可以參考一下2021-12-12
python定間隔取點(diǎn)(np.linspace)的實(shí)現(xiàn)
今天小編就為大家分享一篇python定間隔取點(diǎn)(np.linspace)的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-11-11
Python?搭建?FastAPI?項(xiàng)目的詳細(xì)過程
這篇文章主要介紹了Python搭建FastAPI項(xiàng)目的過程,本文通過圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09

