Python线程计时器

phc*_*aze 1 python multithreading

我在python中有以下脚本,每隔X秒调用一个函数来创建一个新线程:

def function():
    threading.Timer(X, function).start()
    do_something

function()
Run Code Online (Sandbox Code Playgroud)

我的问题是,如果函数需要2 * X秒执行怎么办?由于我正在使用线程,这应该不是问题,对吧?我将同时运行该函数的更多“实例”,但是一旦每个实例完成,其线程都应该被销毁。谢谢

dan*_*ano 5

如果该函数花费2 * X秒,那么您将有多个function同时运行的实例。通过一个例子很容易看到:

import threading
import time

X = 2

def function():
    print("Thread {} starting.".format(threading.current_thread()))
    threading.Timer(X, function).start()
    time.sleep(2*X)
    print("Thread {} done.".format(threading.current_thread()))

function()
Run Code Online (Sandbox Code Playgroud)

输出:

Thread <_MainThread(MainThread, started 140115183785728)> starting.
Thread <_Timer(Thread-1, started 140115158210304)> starting.
Thread <_MainThread(MainThread, started 140115183785728)> done.
Thread <_Timer(Thread-2, started 140115149817600)> starting.
Thread <_Timer(Thread-3, started 140115141424896)> starting.
Thread <_Timer(Thread-1, started 140115158210304)> done.
Thread <_Timer(Thread-4, started 140115133032192)> starting.
Thread <_Timer(Thread-2, started 140115149817600)> done.
Thread <_Timer(Thread-3, started 140115141424896)> done.
Thread <_Timer(Thread-5, started 140115158210304)> starting.
Thread <_Timer(Thread-6, started 140115141424896)> starting.
Thread <_Timer(Thread-4, started 140115133032192)> done.
Thread <_Timer(Thread-7, started 140115149817600)> starting.
Thread <_Timer(Thread-5, started 140115158210304)> done.
Thread <_Timer(Thread-8, started 140115133032192)> starting.
Thread <_Timer(Thread-6, started 140115141424896)> done.
Thread <_Timer(Thread-9, started 140115158210304)> starting.
Thread <_Timer(Thread-7, started 140115149817600)> done.
Thread <_Timer(Thread-10, started 140115141424896)> starting.
Thread <_Timer(Thread-8, started 140115133032192)> done.
Thread <_Timer(Thread-11, started 140115149817600)> starting.
<And on and on forever and ever>
Run Code Online (Sandbox Code Playgroud)

从输出中可以看到,这也是一个无限循环,因此程序永远不会结束。

如果可以安全function地同时运行多个实例,则可以。如果不是,那么您需要function使用锁来保护的非线程安全部分:

import threading
import time

X = 2
lock = threading.Lock()

def function():
    with lock:
        print("Thread {} starting.".format(threading.current_thread()))
        threading.Timer(X, function).start()
        time.sleep(2*X)
        print("Thread {} done.".format(threading.current_thread()))

function()
Run Code Online (Sandbox Code Playgroud)

输出:

Thread <_MainThread(MainThread, started 140619426387712)> starting.
Thread <_MainThread(MainThread, started 140619426387712)> done.
Thread <_Timer(Thread-1, started 140619400812288)> starting.
Thread <_Timer(Thread-1, started 140619400812288)> done.
Thread <_Timer(Thread-2, started 140619392419584)> starting.
Thread <_Timer(Thread-2, started 140619392419584)> done.
Thread <_Timer(Thread-3, started 140619381606144)> starting.
Thread <_Timer(Thread-3, started 140619381606144)> done.
Thread <_Timer(Thread-4, started 140619392419584)> starting.
Thread <_Timer(Thread-4, started 140619392419584)> done.
Thread <_Timer(Thread-5, started 140619381606144)> starting.
Run Code Online (Sandbox Code Playgroud)

最后一点:由于使用了全局解释器锁,在CPython中,一次只能实际执行一个字节码。因此,当您使用线程时,如果您正在执行CPU约束的任务,则并不能真正提高性能,因为一次实际上每个线程仅执行一个线程。相反,操作系统最终会在所有线程之间频繁切换,从而给每个CPU分配了一点时间。由于在线程之间进行切换会增加开销,因此这通常会比单线程方法慢。如果您打算在每个线程中执行CPU限制的工作,则可能要使用它multiprocessing