说明
Threading用于提供线程相关的操作。线程是应用程序中工作的最小单元,它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
thread方法:
- t.start() : 激活线程
- t.getName() : 获取线程的名称
- t.setName() : 设置线程的名称
- t.name : 获取或设置线程的名称
- t.is_alive() : 判断线程是否为激活状态
- t.isAlive() :判断线程是否为激活状态
- t.setDaemon() 设置为后台线程或前台线程(默认:False);通过一个布尔值设置线程是否为守护线程,必须在执行start()方法之前才可以使用。如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,均停止;如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止
- t.isDaemon() : 判断是否为守护线程
- t.ident :获取线程的标识符。线程标识符是一个非零整数,只有在调用了start()方法之后该属性才有效,否则它只返回None
- t.join() :逐个执行每个线程,执行完毕后继续往下执行,该方法使得多线程变得无意义
- t.run() :线程被cpu调度后自动执行线程对象的run方法
简单应用
比如,听歌和玩游戏是可以同时进行的,如果我玩游戏需要5s,听一首歌需要2s,那么玩一把游戏听一首歌和玩一把游戏听两首歌应该是一样的。
import threading
from time import ctime, sleep
def music(func):
for i in range(3):
print "I was listening to {0}. {1}".format(func, ctime())
sleep(1)
def game(func):
for i in range(2):
print "I was playing {0}. {1}".format(func, ctime())
sleep(5)
threads = []
t1 = threading.Thread(target=music, args=(u'cry on my shoulder',))
threads.append(t1)
t2 = threading.Thread(target=game, args=(u'hero League',))
threads.append(t2)
if __name__ == '__main__':
for t in threads:
t.setDaemon(True)
t.start()
t.join() # join()的作用是,在子线程完成运行之前,这个子线程的父线程将一直被阻塞
print "complete at {0}".format(ctime())
结果:
I was listening to cry on my shoulder. Tue Sep 26 15:15:10 2017
I was playing hero League. Tue Sep 26 15:15:10 2017
I was listening to cry on my shoulder. Tue Sep 26 15:15:11 2017
I was listening to cry on my shoulder. Tue Sep 26 15:15:12 2017
I was playing hero League. Tue Sep 26 15:15:15 2017
complete at Tue Sep 26 15:15:20 2017
- setDaemon():
setDaemon(True)将线程声明为守护线程,必须在start() 方法调用之前设置,如果不设置为守护线程程序会被无限挂起。子线程启动后,父线程也继续执行下去,当父线程执行完最后一条语句print “complete at {0}”.format(ctime())后,没有等待子线程,直接就退出了,同时子线程也一同结束。
- join():
join()方法的位置是在for循环外的,也就是说必须等待for循环里的两个进程都结束后,才去执行主进程。
类继承式调用
import threading
from time import ctime, sleep
class GameThread(threading.Thread):
def __init__(self, project):
threading.Thread.__init__(self)
self.project = project
def run(self): # 定义每个线程要运行的函数
for i in range(2):
print "I was playing {0}. {1}".format(self.project, ctime())
sleep(5)
class MusicThread(threading.Thread):
def __init__(self, project):
threading.Thread.__init__(self)
self.project = project
def run(self): # 定义每个线程要运行的函数
for i in range(3):
print "I was listening to {0}. {1}".format(self.project, ctime())
sleep(1)
threads = [MusicThread('cry on my shoulder'), GameThread('hero League')]
if __name__ == '__main__':
for t in threads:
t.setDaemon(True)
t.start()
t.join() # join()的作用是,在子线程完成运行之前,这个子线程的父线程将一直被阻塞
print "complete at {0}".format(ctime())
线程锁
使用线程对数据进行操作的时候,如果多个线程同时修改某个数据,可能会出现不可预料的结果,为了保证数据的准确性,引入了锁的概念。
import threading
import time
num = 0
lock = threading.RLock() # 实例化锁类
def work():
lock.acquire() # 加锁
global num
num += 1
time.sleep(1)
print(num)
lock.release() # 解锁
for i in range(10):
t = threading.Thread(target=work)
t.start()
threading.Event
Event是线程间通信最间的机制之一:一个线程发送一个event信号,其他的线程则等待这个信号。用于主线程控制其他线程的执行。 Events 管理一个flag,这个flag可以使用set()设置成True或者使用clear()重置为False,wait()则用于阻塞,在flag为True之前。flag默认为False。
- Event.wait([timeout]) : 堵塞线程,直到Event对象内部标识位被设为True或超时(如果提供了参数timeout)
- Event.set() :将标识位设为Ture
- Event.clear() : 将标识伴设为False
- Event.isSet() :判断标识位是否为Ture