|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 风琪仙 于 2018-3-24 18:46 编辑
Threading模块 | | | | | | | | | | | 条件变量对象,使得一个线程等待另一个线程满足特定的“条件”,比如改变状态或某个数据值 | | 条件变量的通用版本,任意数量的线程等待某个事件的发生,在该事件发生后所有线程将被激活 | | 为线程间共享的有限资源提供了一个“计数器”,如果没有可用资源时会被阻塞 | | 与 Semaphore 相似,不过它不允许超过初始值 | | 与 Thread 相似,不过它要在运行前等待一段时间 | | 创建一个“障碍”,必须达到指定数量的线程后才可以继续 | | | | | | | | | | | _init_(group=None, tatget=None, name=None, args=(), kwargs ={}, verbose=None, daemon=None) ③ | group: 线程组,目前还没有实现,库引用中提示必须是None; target: 要执行的方法; name: 线程名; args/kwargs: 要传入方法的参数。 | | | | | | | | 直至启动的线程终止之前一直挂起;除非给出了 timeout(超时:秒),否则会一直阻塞后面代码运行 | | | | | | | | 如果是守护线程,则返回 True;否则,返回 False | | 把线程的守护标志设定为布尔值 daemonic(必须在线程 start()之前调用) 1、如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,主线程和后台线程均停止 2、如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止。但如果使用了join将打破这个限制。 | activeCount/ active_count()① | | current Thread() /current_thread① | | | | | | | | | 返回新创建线程的栈大小;或为后续创建的线程设定栈的大小为 size |
Threading两种启动线程方式 | | import threading
'''
threading.Thread 默认的构造函数要求传入 函数名+参数
通过子类化threading.Thread 类。重写构造函数__init__ 重写
运行函数run 实现自定义的线程操作
'''
#创建子类继承自 threading.Thread
class myThread (threading.Thread):
def __init__(self, threadID, threadname):#覆盖threading.Thread构造函数
threading.Thread.__init__(self)
self.threadID = threadID #赋值ID(参数)
self.name = threadname #赋值线程名(参数)
def run(self):#覆盖threading.Thread run方法,threading.Thread类会在start中调用 run!
func(self.name,self.threadID) #运行func
def func(threadName, threadID):
print("线程名:%s 线程ID:%d"%(threadName,threadID))
# 创建新线程
thread1 = myThread(1, "Thread-1")
thread2 = myThread(2, "Thread-2")
# 开启新线程
thread1.start()
thread2.start()
#等待线程完成
thread1.join()
thread2.join()
print ("__________________________________2个线程都完成了")
'''
直接使用threading.Thread
'''
def fu(a,b):
print(a+b)
t=threading.Thread(target=fu,args=(2,1))
t.start()
t.join() |
资源锁同步资源访问 | 只负责数据同步,线程执行顺序跟我没关系!线程说:可能我刚执行完,我又获得了资源锁。 | import threading
from time import sleep
def fn(name):
global const
for i in range(1,10000,1):
#suo.acquire()
const+=1
const-=1
#suo.release()
print(name,const)
const=1
suo=threading.RLock() #锁只能锁只能锁共享资源,而不能挂起别的线程。
t1=threading.Thread(target=fn,args=("线程1",))
t2=threading.Thread(target=fn,args=("线程2",))
t1.start()
t2.start()
print("主线程停止,但子线程还在运行,因为子线程不是后台线程") |
Rlock与lock | | import threading
'''
RLock与Lock区别在于,RLock在同一线程内多次连续使用acquire不会(死锁)
注意:每次调用acquire都必须成对调用一次release,内部维护了一个计数器。
'''
suo=threading.RLock()
#suo=threading.Lock()
suo.acquire()
suo.acquire()
print("<<<<<<<<")
suo.release()
suo.release()
print(">>>>>>>>") |
Condition类 | | import threading
'''
Condition类更加类似Windows中的互斥量,这种方式直接是调度线程方式。
使得线程以一种“推拉”的方式工作。在此模式中访问共享资源的“因果”关系
更加明确!比如:先有产品生产,再有产品销售。
使用资源锁类RLock\Lock 主要实现资源的快速访问,比如某些线程将数据放到队列
又有某些线程从队列取出数据处理,并从队列删除。它们没有特定的“因果”关系,(异步关系)
Condition类更加注重有“因果”关系的数据访问。必须一个过程完成后才能进行下一个过程。
'''
def fn(name):
for i in range(1,1000,1):
global const
if con.acquire(): #获取锁(同一时间只能有一个线程获取锁)
const += 1
print(name, const)
con.notify() # 通知其他线程,(你们可以做好获取锁的准备,我要释放了~)
#con.notifyAll() # 通知所有其他线程(你们可以做好获取锁的准备,我要释放了~)
con.wait() #释放锁,并把自己再次放到线程池,等待通知
const=0
con = threading.Condition() #共享锁
t1=threading.Thread(target=fn,args=("线程1",))
t2=threading.Thread(target=fn,args=("线程2",))
t1.start()
t2.start() |
Event类 | | import threading
from time import sleep
'''
Event类用于异步的异步调度。比如下载文件分段。多个文件下载时,调度线程使用事件管理下面
的子线程。而此调度线程又属于另外一个主线程的子线程。因为在下载文件时不仅仅只下载一个文件
每个下载任务都是可控的,比如:暂停,开始.
多线程中,被调度后,环境都是保存的(注意)
'''
def fn(name):
s=0
for i in range(1,1000,1):
global const
if ev.wait(): #等待通知
const += 1
s+=1
print(name, const,s)
const=0
ev = threading.Event() #创建事件
t1=threading.Thread(target=fn,args=("线程1",))
t2=threading.Thread(target=fn,args=("线程2",))
t1.start()
t2.start()
ev.set() #设置标志为真,通知所有线程运行。
#ev.isSet() #是否设置了标志。当内置标志为True时返回True。
ev.clear() #清除标志。所有使用该事件的线程会立马停止!
ev.set()
sleep(0.0001)
#ev.clear()
print("End") #注意由于不是后台线程,主线程结束后,子线程还在运行。除非调用clear或子线程自然结束。 |
Timer | | import threading
from time import sleep
'''
Time类,定时器,跟Windows定时器不同,这里的Timer是延迟执行。
'''
def fn():
for i in range(1,1000,1):
global const
const += 1
print(const)
const=0
time=threading.Timer(1,fn)#设置延迟时间,要调用的函数
time.start()#开始执行。 |
验证多线程运行同一个函数,局部变量问题 | | import threading
from time import sleep
def fn2(name,index,v):
s=[1,2,3,4,5,6]
print("线程:%s开始执行!并完成s的赋值"%(name,))
suo.acquire() #获取锁
s[index]=v
print(name, s)
sleep(5) #延时,模拟代码复杂度。
suo.release() #释放锁
suo=threading.RLock()
print("___________________多线程运行同一函数,函数内变量是【可变类型】")
t1=threading.Thread(target=fn2,args=("线程1",0,6666))
t2=threading.Thread(target=fn2,args=("线程2",1,9999))
t1.start()
t2.start()
'''
输出:
线程1 [6666, 2, 3, 4, 5, 6]
线程2 [1, 9999, 3, 4, 5, 6]
'''
#结论:线程在运行同一个函数时,函数内部局部变量都是独立的! 线程间互相不影响
|
线程局部类local | | import threading
'''
对于同一个local,线程无法访问其他线程设置的属性;线程设置的属性不会被其他线程设置的同名属性替换。
总结:给你要个全局量,你们各玩各的。一般这个量是要个通用的属性量。线程内可以进行设置。
函数内的的局部量也是各玩各的。如果是全局量就要指定这个。
'''
local = threading.local()
local.tname = 1
def func():
for i in range(1,10,1):
local.tname+=2 #local.tname+=2 错误?只能赋值常数?
print("子线程输出:%d"%(local.tname))
t1 = threading.Thread(target=func)
t1.start()
t1.join()
print("——————主线程输出:%d"%(local.tname))
'''
子线程输出:2
子线程输出:2
子线程输出:2
子线程输出:2
子线程输出:2
子线程输出:2
子线程输出:2
子线程输出:2
子线程输出:2
——————主线程输出:1
''' |
Barrier类 | | import threading
from time import sleep
''' 应用:多线程下载一个文件时,由于每个线程下载不同的片段,可能有些线程下载速度 较快,提前完成了,而有的线程下载较慢,还在下载,Barrier可以等待所有线程下载 完成后,整合成一个完整的文件。
0、wait:线程已经就位。超时参数:timeout 比喻:有女嘉宾等急了,都到了这么久了还
有人没来,已经到我的底线了,我要搞点事情。超时会进入broken状态,如果栅栏 在处于
broke状态的时候调用reset函数会抛出一个BrokenBarrierError异常。
1、reset:设置为初始状态 所有已经在等待的线程会接收到BrokenBarrierError异常
(如果没填满,其他线程就死锁了,需要异常处理)比喻:由于某个女嘉宾原因,节目
组场地换了,而其他女嘉宾还在去原先节目组场地,有些的已经到节目组场地了,这时
节目组打电话(异常)通知女嘉宾们换场地了(女嘉宾们重新去新的目的地)。
2、abort:设置为打破状态。所有已经在等待的线程 都会接收到BrokenBarrierError异常
比喻:由于白衣光头少年的”光大亮节“,女嘉宾们生气了,节目搞不下去了。其中一个或
多个女嘉宾闹事了。(台子被掀翻了)节目搞不下去咯。而其他女嘉宾还不知道,节目组只能
通知(异常)所有女嘉宾们,今天就到这里吧。
【节目组(主线程)的监视器】属性
n_waiting:正在等待本 barrier 的线程的数量(女嘉宾来了几个人了?)
broken:栅栏是否为broken状态,返回一个布尔值(女嘉宾是否闹事了?)
【节目组:和谐最重要,没事尽量不要搞事情^_^】
'''
def fn(name,time):
for i in range(1,10,1):
sleep(time)
print(name,i)
ba.wait() #每一次调用对"栅栏"进行一次填空。
def ting(): #线程数量到达设定数量(填满了),栅栏自动复原并调用这个监听函数。
print("光头白衣少年:下一批~")
print("主持人:3位靓丽女嘉宾靓丽登场。你对谁最有感觉?")
t1=threading.Thread(target=fn,args=("线程1执行:",0.1)) #创建线程,并给它们设置不同延时,模拟代码复杂度的不同
t2=threading.Thread(target=fn,args=("线程2执行:",0.2))
t3=threading.Thread(target=fn,args=("线程3执行:",0.3))
ba=threading.Barrier(parties=3,action=ting) #多对象(线程)等待。只有当全部线程都运行结束时才返回
t1.start()#启动所有线程(女嘉宾登场了)
t2.start()
t3.start()
#由于节目组要求,主办方不能提前退场(等待所有子线程结束)
t1.join()
t2.join()
t3.join()
print("主办方:泪牛满面。。。") |
Semaphore信号量 | | import threading
from time import sleep
'''
应用:当程序限制运行任务数时非常有用,可以控制,最多有多少个线程同时运行。
比如写要一个服务器,同一时间有多个请求到来,不可能来一个请求,就处理一个请求
如果这样,其他人的请求就收不到了。这时可以通过主线程创建会话线程放到队列,再使用
信号量对象,根据服务器当前状态,设置并行处理数量。
'''
def fn(name):
for i in range(1,10,1):
sp.acquire() #占用
print(name, "占坑闭关")
sleep(0.5)
sp.release() #释放
t1=threading.Thread(target=fn,args=("线程1执行:",)) #创建线程
t2=threading.Thread(target=fn,args=("线程2执行:",))
t3=threading.Thread(target=fn,args=("线程3执行:",))
sp=threading.Semaphore(2) #创建信号量(好,这里有个厕所,只有2个坑)
t1.start()#启动所有线程(有3个人要WC了)
t2.start()
t3.start() |
|
|