python3 threading模块_【PYTHON模块】threading模块

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()

参考资料:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值