赞
踩
threading模块:利用CPU空闲时间执行多任务。Python的多线程实际是遇到IO操作就CPU切换到其它任务。
1、GIL (Global Interpreter Lock):全局解释器锁
作用就是保证同一时刻CPU只执行一个线程。只有CPython有GIL锁。
2、简单的threading使用常用类和方法名:参数作用示例
threading.enumerate()用列表,列出所有活动的线程名和ID
示例中列出的是s = threading.enumerate()
for v in s:
print(v.name)
threading.Tread.isAlive(线程实例名)线程实例名:下面的thread_create判断线程是否正在运行,返回True或Falsethreading.Tread.isAlive(ss)
或者
i.isAlive() #i是创建的Thread实例
thread_create=threading.Thread()target:加入多线程的对象名
args:对象的参数,元组形式
kwargs:对象的字典参数
name:指定线程名,默认Thread-N把一个对象实例化成一个线程对象thread_create = threading.Tread(target=work,args=('tom',),kwargs={'work_name':'eat'})
thread_create.start()启动线程thread_create.start()
thread_create.join()timeout:线程阻塞的时间(超时时间)
timeout默认,等待此线程执行完毕等待至线程中止或timeout超时,再继续执行程序thread_create.join(5)
或者
thread_create.join(timeout=5)
thread_create.getName()获取thread_create线程名thread_create.getName()
thread_create.setName()name:线程名设置thread_create线程名,这个名字只是标识thread_create.setName('th1')"""
简单的例子
可以使用两种方法创建多线程
"""
#方法一:函数式调用。
import time,random
import threading
work_list = ["睡觉" ,"吃饭", "学习" ,"嗯哼"] # 工作列表
def work(name, cost):
'''定义函数'''
print(" 你开始 [31;2m{}[0m".format(name))
time.sleep(cost)
print("{} 竟然只用了{}秒钟!".format(name, cost))
thread_list = [] # 线程列表
start_time = time.time() # 记录开始的时间
# 线程开始
for i in work_list:
#循环读取工作内容
cost_time= random.randint(5,10) # 生成随机时间,传输给函数
# 创建多线程实例
t = threading.Thread(target = work,args=(i,cost_time))
thread_list.append(t) # 把实例内存地址存储到列表,后续使用
t.start() # 开启线程
active_thread = threading.enumerate() #列出当前所有活动的线程
print(active_thread) #结果是一个列表
for i in active_thread:
print (i.name) # 调用线程的name属性,表出线程名,实际是调用Thread类析构函数的self.name属性,在方法二里面会看到线程名和工作名是一样的
print(i.getName()) # 获取当前线程名称
i.setName("change-name"+i.name) #改名
print(i.getName()) # 重新获取线程名字
for i in thread_list: # 从列表里读取线程地址
i.join() # 每个线程加入阻塞,默认值等每个线程都结束,继续运行
end_time = time.time() # 记录结束的时间
sum_time = end_time - start_time # 计算总耗时
print ('总用时:{}'.format(sum_time))'''方法二:重构Thread类的run函数,请注意,只能重构__init__和run函数,其它的不要重构!!!!!'''
import time,random
import threading
'''重写run方法调用'''
work_list = ["睡觉" ,"吃饭", "学习" ,"嗯哼"] # 工作列表
class work(threading.Thread):
def __init__(self,name,cost):
threading.Thread.__init__(self)
self.name = name
self.cost = cost
def run(self):
self.do_work()
def do_work(self):
"""工作函数"""
print(" 你开始 [31;2m{}[0m".format(self.name))
time.sleep(self.cost)
print("{} 竟然只用了{}秒钟!".format(self.name, self.cost))
start_time = time.time()# 记录开始的时间
thread_list = []
for i in work_list:
cost_time = random.randint(5,9)
t = work(i, cost_time)
thread_list.append(t)
t.start()
active_thread = threading.enumerate()
for i in active_thread:
print(i.name)# 打印出来的是工作名称,不是Thread-N这个形式的!!!
for i in thread_list:
i.join()
end_time = time.time()# 记录结束的时间
sum_time = end_time - start_time# 计算总耗时
print ('总用时:{}'.format(sum_time))
3、守护线程deamon
类、方法、属性名参数作用示例
setDaemon(BOOL)BOOL:True
False设置线程为父线程的守护线程,必须在strar()线程开始前设置。m为创建的进程实例。
m.setDaemon(True)
isDaemon()无判断当前线程是否设置了守护线程
返回BOOL型,True 或 Falsem.isDaemon()"""守护线程Daemon实例"""
import time,random
import threading
work_list = ["睡觉" ,"吃饭", "学习" ,"嗯哼"] # 工作列表
def work(name, cost):
'''定义函数'''
print(" 你开始 [31;2m{}[0m".format(name))
time.sleep(cost)
print("{} 竟然只用了{}秒钟!".format(name, cost))
def main_work(name):
w = threading.Thread(target = work, args=("嗯哼",10))
w.start()
w.join(9)
start_time = time.time() # 记录开始的时间
m = threading.Thread(target = main_work, args=('Done',))
m.setDaemon(True) # 设置守护进程,主线程完成,main_work结束,main_work的子线程也结束
m.start()
m.join(2)
end_time = time.time()
print("你{}了!!!".format("Done"))
print ("总耗时:",end_time-start_time)
#-------------执行结果--------------
你开始 [31;2m嗯哼[0m
你Done了!!!
总耗时: 2.0008544921875
#--因为设置m为守护线程,所以当主线程执行结束后,m和由m生成的所有线程都随着主线程结束。
4、线程锁Lock、递归锁Rlock
加锁以后线程依次运行。
类、方法、属性名参数作用示例
Lock()Lock类,用于创建Lock对象lock = threading.Lock()
Rlock()Rlock类,用于创建递归锁,也叫做多重锁
同一线程可以acquire()多次,但要对应相同数量的release()rlock = threading.Rlock()
acquire()Lock和Rlock的方法:
启用线程锁lock.acquire()
release()Lock和Rlock的方法:
释放线程锁lock.release()###Lock实例###
import time,random
import threading
work_list = ["睡觉" ,"吃饭", "学习" ,"嗯哼"] # 工作列表
def work(name,cost):
'''定义函数'''
lock.acquire() #线程锁启用
work_list[name] = name
time.sleep(cost)
print("time:{},list:{}".format(cost,work_list))
lock.release() #线程锁释放,只有释放后,才能运行其它线程
start_time = time.time() # 记录开始的时间
thread_list = []
lock = threading.Lock()
for i in range(3):
m = threading.Thread(target = work, args=(i,3))
thread_list.append(m)
m.start()
for i in thread_list:
i.join()
end_time = time.time()
print ("总耗时:",end_time-start_time)
-----------------加锁版运行结果------------------
time:3,list:[0, '吃饭', '学习', '嗯哼']
time:3,list:[0, 1, '学习', '嗯哼']
time:3,list:[0, 1, 2, '嗯哼']
总耗时: 9.002515077590942
-----------------不加锁运行结果------------------
time:3,list:[0, 1, 2, '嗯哼']
time:3,list:[0, 1, 2, '嗯哼']
time:3,list:[0, 1, 2, '嗯哼']
总耗时: 3.002171516418457
5、信号量(semaphore)
类、方法、属性名参数作用示例
BoundedSemaphore(num)num:int型,只允许num个线程同时运行创建一个semaphore对象semaphore = threading.BoundedSemaphore(3)
acquire()把线程加入信号量对象semaphore .acquire()
release()把线程从信号量对象中删除semaphore .release()待测试
import threading,time,random
work_list = ["睡觉" ,"吃饭", "学习" ,"嗯哼"] # 工作列表
def work(name,cost):
semaphore.acquire()
print("{}用了{}分钟".format(name,cost))
time.sleep(cost)
#print(name)
semaphore.release()
thread_list=[]
semaphore = threading.BoundedSemaphore(3)
index = ""
for i in work_list:
index = index+str(work_list.index(i))
num = random.randint(2,5)
t = threading.Thread(target=work, args = (i+index,num))
thread_list.append(t)
t.start()
for j in thread_list:
j.join()
print ("Done")
#------------结果------------
睡觉0用了2分钟
吃饭01用了5分钟
学习012用了4分钟
#以上三个先出现,下面一行后出现,说明了一次只能运行三个线程
嗯哼0123用了2分钟
5、定时器(Timer)
类、方法、属性名参数作用示例
Timer(time,func,args)time:延时时间(单位:秒)
func:要执行的函数名
args:参数,与多进程使用方法一样生成定时器实例,过time的时长后,执行func的功能。timer=threading.Timer(3,work,('David',))
start()启动定时器timer.start()
stop()停止定时器timer.stop()import threading
def work(name):
print ("循环:{}".format(name))
global timer
timer=threading.Timer(3,work,('David',))
timer.start()
timer=threading.Timer(3,work,('David',))
timer.start()
6、事件(Event)
Event是线程同步的一种方式,类似于一个标志,当该标志为false时,所有等待该标志的线程阻塞,当为true时,所有等待该标志的线程被唤醒。
Event是一个重要的概念,有一个编程思想叫事件驱动模型。稍后讨论。
类、方法、属性名参数作用示例
Event()无实例化事件对象e = threading.Event()
isSet()无判断事件标志,返回True或Falsee.isSet()
set()无设置事件标志,isSet()为Truee.set()
clear()无清除事件标志,isSet()为Truee.clear()
wait(timeout)timeout:时间
####事件驱动的红绿灯实例####
import threading
import time
class traffic(threading.Thread):
'''使用继承类方式写一个进程'''
def __init__(self,event_obj):
threading.Thread.__init__(self)
self.event_obj = event_obj # 传递事件对象
def light(self):
sec = 1 # 秒数
while True:
if sec / 1 == 1: # 初始绿灯
self.event_obj.set() # 设置事件标志
print ('green...')
elif sec / 5 == 1: # 计数5秒,变黄灯,黄灯可以通行,所以不改变事件标志
print ('yellow...')
elif sec / 7 == 1: # 计数7秒,变红灯
self.event_obj.clear() # 清除事件标志
print('red...')
elif sec == 10: # 到10秒重新计数
sec = 1
continue
sec += 1
time.sleep(1) # 延迟
def run(self):
# 重写run函数,启动灯。
self.light()
def car(event_obj):
# 汽车通行函数
while True:
if event_obj.isSet(): # 判断事件标志是True,代表绿灯,打印通行
print('the car is running!')
else: # 判断事件标志是False,代表红灯,打印通行
print('the car is stop!')
time.sleep(1) # 延迟
def exit():
# 定义控制函数,检测鼠标输入,C则结束所有进程,退出程序
t = traffic(e) # 创建信号灯线程对象
c = threading.Thread(target=car, args=(e,)) # 创建汽车线程对象
t.setDaemon(True) # 把两个设置成守护线程,跟随exit结束
c.setDaemon(True)
t.start() # 线程启动
c.start()
while True: # 循环检测键盘输入
s = input().strip() # 读取键盘输入字符
if s == 'c': # 如果为C,结束exit
print('程序退出!')
return
e = threading.Event() # 创建事件对象
ex=threading.Thread(target=exit) # 创建exit进程对象
ex.start()
ex.join()
参考资料:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。