我现在进入线程并探索线程和线程库。当我开始使用它们时,我写了两个基本程序。以下是2个程序及其相应的输出:
import threading
def main():
t1=threading.Thread(target=prints,args=(3,))
t2=threading.Thread(target=prints,args=(5,))
t1.start()
t2.start()
t1.join()
t2.join()
def prints(i):
while(i>0):
print "i="+str(i)+"\n"
i=i-1
if __name__=='__main__':
main()
i=3
i=2
i=5
i=4
i=1
i=3
i=2
i=1
import thread
import threading
def main():
t1=thread.start_new_thread(prints,(3,))
t2=thread.start_new_thread(prints,(5,))
t1.start()
t2.start()
t1.join()
t2.join()
def prints(i):
while(i>0):
print "i="+str(i)+"\n"
i=i-1
if __name__=='__main__':
main()
Traceback (most recent call last):
i=3
File "thread_1.py", line 19, in <module>
i=2
i=1
main()
i=5
i=4
i=3
i=2
i=1
File "thread_1.py", line 8, in main
t1.start()
AttributeError: 'int' object has no attribute 'start'
我想要的输出与threading_1.py一样,其中交错打印使其成为线程执行的令人信服的示例。我的理解是“threading”是一个更高级的库与“thread”相比。我在thread_1.py中得到的 AttributeError 是因为我在一个从线程库开始而不是线程的线程上运行。
所以,现在我的问题是 - 如何使用thread_1.py实现类似于threading_1.py输出的输出。可以修改或调整程序以产生相同的结果吗?
答案 0 :(得分:1)
简短回答:忽略thread
模块,然后使用threading
。
thread
和threading
模块的用途完全不同。 thread
模块是一个用C语言编写的低级模块,旨在抽象出平台差异并提供一个最小跨平台原语集(基本上是线程和简单锁)作为更高级API的基础。如果您将Python移植到不支持现有线程API的新平台(例如POSIX线程),那么您必须编辑thread
模块源,以便可以包装适当的OS-级别调用在您的新平台上提供相同的原语。
作为一个例子,如果你看一下当前的CPython实现,你会发现Python Lock
基于Linux上的未命名POSIX信号量,基于POSIX条件变量和POSIX互斥量的组合。 OS X(不支持未命名的信号量),以及Event
和Windows特定的库调用集合,在Windows上提供各种原子操作。作为Python用户,您不必关心这些细节。 thread
模块提供了抽象层,使您可以构建更高级别的代码,而无需担心平台级别的详细信息。
因此,thread
模块实际上是为那些开发Python而不是那些使用它的人提供便利:它不是普通Python用户需要处理的东西。出于这个原因,该模块已在Python 3中重命名为_thread
:前导下划线表示它是私有的,并且用户不应该依赖其API或行为。
相比之下,threading
- 模块是一个用Python编写的Java启发模块。它建立在thread
模块奠定的基础之上,为启动和加入线程提供了方便的API,以及一组广泛的并发原语(可重入锁,事件,条件变量,信号量,障碍等)对于用户。这几乎总是您作为Python用户想要使用的模块。如果您对幕后发生的事情感兴趣,那么值得花些时间查看threading
source:您可以看到threading
模块如何从{{1}中获取所需的原语模块并将所有内容放在一起以提供更高级别的API。
请注意,从Python核心开发人员的角度来看,这里有不同的权衡。一方面,将Python移植到新平台应该很容易,因此thread
模块应该很小:您只需要实现一些基本原语来启动并运行在新平台上。相比之下,Python 用户需要各种各样的并发原语,因此thread
库需要广泛来支持这些用户的需求。将线程功能拆分为两个单独的层是提供用户需求的一种好方法,同时不会使在各种平台上维护Python变得不必要。
要回答您的具体问题:如果您必须直接使用threading
库(尽管我上面已经说过),您可以这样做:
thread
但是当然,使用import thread
import time
def main():
t1=thread.start_new_thread(prints,(3,))
t2=thread.start_new_thread(prints,(5,))
def prints(i):
while(i>0):
print "i="+str(i)+"\n"
i=i-1
if __name__=='__main__':
main()
# Give time for the output to show up.
time.sleep(1.0)
是处理主线程中的事情的一种非常伪劣的方式:实际上,我们希望等到两个子线程在退出之前完成它们的工作。所以我们需要构建一些主线程可以等待子线程的功能。该功能并不直接存在于time.sleep
模块中,而是存在于thread
中:这正是threading
模块的要点:它提供了丰富易用的API取代最小的,难以使用的threading
API。我们回到摘要栏:不要使用thread
,请使用thread
。