Python线程计时器

时间:2014-10-03 19:54:20

标签: python multithreading

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

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

function()

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

3 个答案:

答案 0 :(得分:4)

如果函数需要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()

输出:

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>

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

如果同时运行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()

输出:

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.

最后要注意的是:由于Global Interpreter Lock,在CPython中,一次只能有一个线程实际执行字节码。因此,当您使用线程时,如果您正在执行CPU绑定任务,那么您并没有真正提高性能,因为每次实际只执行一个线程。相反,操作系统最终会频繁地在所有线程之间切换,从而为每个线程提供一些CPU时间。这通常会比单线程方法慢,因为线程之间切换的额外开销。如果您计划在每个线程中执行CPU绑定工作,则可能需要使用multiprocessing

答案 1 :(得分:0)

如果函数的一个实例正在写入资源而另一个实例正在尝试读取同一资源,则可能会遇到竞争条件。

http://en.wikipedia.org/wiki/Multithreading_(computer_architecture)#Disadvantages

您可以设置一个测试,以便您可以试验您所关注的行为吗?

答案 2 :(得分:0)

理论上,你可以在任何给定的时间运行3个活动线程:一个即将结束,一个正在运行中,一个刚刚生成。

|-----|
   |-----|
      |-----|   

在实践中,您可能会得到更多:

import threading
import logging
logger = logging.getLogger(__name__)
import time

def function():
    threading.Timer(X, function).start()
    logger.info('{} active threads'.format(threading.active_count()))
    time.sleep(2*X)


logging.basicConfig(level=logging.DEBUG,
                    format='[%(asctime)s %(threadName)s] %(message)s',
                    datefmt='%H:%M:%S')

X = 3
function()

产量

[16:12:13 MainThread] 2 active threads
[16:12:16 Thread-1] 3 active threads
[16:12:19 Thread-2] 4 active threads
[16:12:22 Thread-3] 4 active threads
[16:12:25 Thread-4] 5 active threads
[16:12:28 Thread-5] 4 active threads
[16:12:31 Thread-6] 4 active threads
[16:12:34 Thread-7] 4 active threads
[16:12:37 Thread-8] 5 active threads
[16:12:40 Thread-9] 4 active threads
[16:12:43 Thread-10] 5 active threads
[16:12:46 Thread-11] 5 active threads

我没有看到任何固有的问题;你只需要知道它在做什么。