[Python 多線程] Timer定時器/延遲執行、Event事件 (七)


 

Timer繼承子Thread類,是Thread的子類,也是線程類,具有線程的能力和特征。這個類用來定義多久執行一個函數。

它的實例是能夠延遲執行目標函數的線程,在真正執行目標函數之前,都可以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傳入間隔時間,function傳入線程執行的函數,args和kwargs傳入函數的參數。

 

提前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===")

運行結果:
===end===

  start方法執行之后,Timer對象會處於等待狀態,等待10秒之后會執行add函數。同時,在執行add函數之前的等待階段,主線程使用了子線程的cancel方法,就會跳過執行函數結束。

 

使用event 事件實現Timer計時器:

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()

運行結果:
WARNING:root:9

  Event事件,是線程間通信機制中最簡單的實現,使用一個內部的標記flag,通過flag的True或False的變化來進行操作。

 

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設置為True
  • clear()                 flag設置為False
  • is_set()                flag是否為True,返回布爾值
  • wait(timeout=None)  設置等待flag變為True的時長,None為無限等待。等到了返回True,未等到超時了就返回False。

 

舉例:

老板雇佣了一個工人,讓他生產杯子,老板一直等着工人,直到生產了10個杯子。

import threading
import logging
import time
logging.basicConfig(level=logging.INFO)

cups = []
event = threading.Event()#event對象

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設置為True
            break

b = threading.Thread(target=boss,name='boos',args=(event,))
w = threading.Thread(target=worker,args=(10,event))

w.start()
b.start()

運行結果:
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.

  老板和工人使用同一個Event對象的標記flag。

  老板wait()設置為最多等待30秒,等待flag變為True,工人在做夠10杯子時,將flag設置為True,工人必須在30秒之內沒有做好杯子。

 

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.')

運行結果:
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的區別是:wait會主動讓出時間片,其它線程可以被調度,而sleep會占用時間片不讓出。

 

小結:

Timer定時器繼承自Thread類,也是線程類。它的作用是等待n秒鍾之后執行某個目標函數,可以使用cancel提前取消。

Event事件是通過True和False維護一個flag標記值,通過這個標記的值來決定做某事,wait()方法可以設置最長等待flag設置為Ture的時長,超時還未設置為True就返回False。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM