2014-10-03 72 views
0

我已经在Python下面的脚本调用一个函数每X秒创建一个新的线程:Python的线程定时器

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

function() 

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

回答

3

如果该函数需要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. 

最后一点:由于全局解释器锁的,在CPython一次只能有一个线程实际执行字节码。所以当你使用线程时,如果你正在执行CPU绑定任务,那么你并没有真正提高性能,因为一次只有一个线程实际执行。相反,操作系统经常在所有线程之间切换,并给每个CPU时间一点点时间。这通常最终会比单线程方法慢,因为在线程之间切换的额外开销。如果您打算在每个线程中执行CPU绑定的工作,则可能需要使用multiprocessing

+0

非常好的答案谢谢。我想在每个线程中执行的操作是从数据库中读取URL并刮取网页。 – phcaze 2014-10-04 06:56:31

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 

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