随着时间的推移验证连续条件

时间:2019-02-02 16:23:48

标签: python multithreading time concurrency python-multithreading

我想开发python程序,从时间的时刻开始,执行动作之前等待60秒。该程序必须具有的另一个功能是,如果我更新了初始时间,则必须开始检查条件。我想过用线程做,但我不知道如何停止线程,并把它与新的开始时间重新开始。

import thread
import time


# Define a function for the thread
def check_message (last, timer):
    oldtime = time.time()
    print oldtime
    # check
    while time.time() - oldtime <= 60:
    print (time.time() - oldtime)
    print "One minute"+ str(time.time())
    return 1

# Create two threads as follows
try:
    named_tuple = time.localtime() # get struct_time
    time_string = time.strftime("%H:%M:%S", named_tuple)
    thread.start_new_thread(check_message , (time_string, 60))
except:
    print "Error: unable to start thread"

while 1:
    pass

谢谢!

2 个答案:

答案 0 :(得分:3)

在这里不必检查循环时间,这很浪费,因为您可以让线程进入睡眠状态,如果时间到了,让内核将其唤醒。 线程库为此类用例提供了threading.Timer。你的情况的困难是,你不能中断这种休眠线程以调整后应执行的指定功能的时间间隔。

在下面的示例中,我正在使用自定义经理类TimeLord,以克服此限制。它增加了一个包装工人功能,设置一个标志,当目标函数 开始执行。父线程将检查此标志,以决定您是否仍可以调整执行或为时已晚。如果还不算太晚,请使用新计时器 将以timelord.reset方法中指定的新间隔开始。

此代码与Python 2和3运行:

import time
from datetime import datetime
from threading import Timer, current_thread


def f(x):
    print('{} {} performing action with {}'.format(
        datetime.now(), current_thread().name, x)
    )
    time.sleep(10)
    print('{} {} exiting'.format(datetime.now(), current_thread().name))


class TimeLord:
    """
    Manager Class for threading.Timer instance. Allows "resetting" `interval`
    as long execution of `function` has not started by canceling the old
    and constructing a new timer instance.
    """

    def worker(self, *args, **kwargs):
        self._timer.executing = True
        self.func(*args, **kwargs)

    def __init__(self, interval, function, args=None, kwargs=None):
        self.func = function
        self.args = args if args is not None else []
        self.kwargs = kwargs if kwargs is not None else {}
        self._init_timer(interval)

    def _init_timer(self, interval):
        self._timer = Timer(interval, self.worker, self.args, self.kwargs)
        self._timer.daemon = True
        self._timer.executing = False # In Python 2 Timer is a
        # factory function, so we can't add this by subclassing Timer.

    def start(self):
        self._timer.start()
        print('{} Timer-thread with `interval={}` started'.format(
            datetime.now(), self._timer.interval)
        )  # DEBUG

    def reset(self, interval):
        """Try to cancel old timer and start a new one if cancellation was
        successful.
        """
        print('{} cancel Timer-thread'.format(datetime.now()))  # DEBUG
        self._timer.cancel()  # this order prevents race condition and is
        # potentially redundant

        # start new thread only if existing one is not already executing
        # `function`.
        if self._timer.is_alive() and not self._timer.executing:
            self._init_timer(interval)
            self.start()

    def cancel(self):
        self._timer.cancel()

    def join(self, timeout=None):
        self._timer.join(timeout=timeout)

def run_demo(initial_interval):

    x = 'x'
    print("testing with initial interval {}".format(initial_interval))
    tl = TimeLord(interval=initial_interval, function=f, args=(x,))
    tl.start()

    print('{} sleeping two seconds'.format(datetime.now()))
    time.sleep(2)

    tl.reset(interval=10)
    tl.join()
    print("-" * 70)


if __name__ == '__main__':

    run_demo(initial_interval=5)
    run_demo(initial_interval=1)

示例输出:

testing with initial interval 5
2019-02-02 22:58:12.594050 Timer-thread with `interval=5` started
2019-02-02 22:58:12.594101 sleeping two seconds
2019-02-02 22:58:14.596165 cancel Timer-thread
2019-02-02 22:58:14.596889 Timer-thread with `interval=10` started
2019-02-02 22:58:24.596810 Thread-2 performing action with x
2019-02-02 22:58:34.605854 Thread-2 exiting
----------------------------------------------------------------------
testing with initial interval 1
2019-02-02 22:58:34.606483 Timer-thread with `interval=1` started
2019-02-02 22:58:34.606541 sleeping two seconds
2019-02-02 22:58:35.606587 Thread-3 performing action with x
2019-02-02 22:58:36.608610 cancel Timer-thread
2019-02-02 22:58:45.616692 Thread-3 exiting
----------------------------------------------------------------------

Process finished with exit code 0

请注意,间隔为1时,两秒后取消无效,因为计时器已在执行目标功能。

答案 1 :(得分:0)

一种选择是在线程外进行检查,以便主循环每60秒执行一次执行X任务的线程:

import threading
import time

# Define a function for the thread
def check_message():
    print("One minute"+ str(time.time()))
    return 1

last_execution = time.time()
while 1:
    if time.time() - last_execution < 60:
        time.sleep(1)
    else:
        last_execution = time.time()
        threading.Thread(target=check_message).start()
        # Python2:
        # import thread
        # thread.start_new_thread(check_message)

由于我没有安装Python2,因此我将代码替换为可在Python3中使用的语法。但总体思路在两个版本中都应相同。