threading模块的Thread类是主要的执行对象。它有很多thread没有的函数。
属性 | 描述 |
---|---|
name | 线程名 |
ident | 线程的标识符 |
daemon | 布尔标志,表示这个线程是否是守护线程 |
init(group=None,target=None,name=None,args=(),kwargs={},verbose=None,daemon=None) | 实例化一个线程对象,需要有一个可条用的target,以及其参数args或kwargs。还可以传递name或group参数,不过后者还未实现。此外,verbose标志也是可接受的。而daemon的值将会设定thread.daemon属性/标志 |
start() | 开始执行该线程 |
run() | 定义线程功能的方法(通常在子类中被重写) |
join(timeout=None) | 直至启动的线程终止之前一直挂起,除非给出timeout否则会一直阻塞 |
getName() | 返回线程名 |
setName(name) | 设定线程名 |
isAlivel/is_alive() | 布尔标志,表示这个线程是否还存活 |
isDaemon() | 如果是守护线程,返回true,反之返回false |
setDaemon(daemonic) | 把线程的守护标志设定为布尔值。 |
下面我们看一个实例来分析:
from time import sleep,ctime
import threading
loops = [4,2]
def loop(nloop,nesc):
print("start loop",nloop,"at:",ctime())
sleep(nesc)
print("loop",nloop,"end at:",ctime())
def main():
print("start at:",ctime())
threads = []
nloops = range(len(loops))
for i in nloops:
t = threading.Thread(target=loop,args=(i,loops[i]))
threads.append(t)
for i in nloops:
threads[i].start()
for i in nloops:
threads[i].join()
print("all end at:",ctime())
if __name__ == "__main__":
main()
运行后输出:
start at: Mon Sep 10 22:42:35 2018
start loop 0 at: Mon Sep 10 22:42:35 2018
start loop 1 at: Mon Sep 10 22:42:35 2018
loop 1 end at: Mon Sep 10 22:42:37 2018
loop 0 end at: Mon Sep 10 22:42:39 2018
all end at: Mon Sep 10 22:42:39 2018
老学员估计已经发现问题了,这个例子跟上节的例子长得有点相似呀。确实,我们就是以它为原型修改而来的。但是他们有什么不同呢?
首先我们使用的thread模块的锁没有了,取而代之的是一组Thread对象,当实例化每个Thread对象时,把函数target和参数args传进去,然后返回Thread实例。实例化Thread的最大区别就是新线程不会立即执行。这是一个非常有用的同步功能,尤其是当你并不想让线程立即开始执行的时候。
当我们把所有资源都分配好了之后,再调用start()方法去执行他们。相比于去管理一组锁而言,这里只需要为每个线程调用join()方法即可。join方法将等待线程结束,使用join要比等待锁释放更加优雅清晰。
一天一个小知识点,明天继续。
更多内容请关注公众号“计算机自学平台”