我已经在Python下面的脚本调用一个函数每X秒创建一个新的线程:Python的线程定时器
def function():
threading.Timer(X, function).start()
do_something
function()
我的问题是,如果函数需要什么2 * X秒执行?由于我使用线程,这应该不成问题,对吧?我将有更多的“实例”在同一时间运行的功能,但一旦完成其线程应该被销毁。谢谢
我已经在Python下面的脚本调用一个函数每X秒创建一个新的线程:Python的线程定时器
def function():
threading.Timer(X, function).start()
do_something
function()
我的问题是,如果函数需要什么2 * X秒执行?由于我使用线程,这应该不成问题,对吧?我将有更多的“实例”在同一时间运行的功能,但一旦完成其线程应该被销毁。谢谢
如果该函数需要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
。
如果函数的一个实例正在写入资源而另一个实例正在尝试读取同一资源,则可能会遇到争用条件。
http://en.wikipedia.org/wiki/Multithreading_(computer_architecture)#Disadvantages
你设置一个测试,让你可以与你关心的是行为实验可?
理论上你可以在任何给定的时间运行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
我没有看到任何这方面的固有问题;你只需要知道它在做什么。
非常好的答案谢谢。我想在每个线程中执行的操作是从数据库中读取URL并刮取网页。 – phcaze 2014-10-04 06:56:31