[Python 多线程] Barrier (十一)
Barrier
栅栏,也叫屏障。可以想象成路障、道闸。
Python 3.2引入的新功能。
构造方法:
threading.Barrier(parties, action=None, timeout=None)
构建Barrier对象,parties 指定参与方数目,timeout是wait方法未指定时超时的默认值。
n_waiting 当前在栅栏中等待的线程数
parties 通过栅栏所需的线程数
wait(timeout=None) 等待通过栅栏,返回0到线程数-1的整数(barrier_id),每个线程返回不同。如果wait方法设置了超时,并超时发送,栅栏将处于broken状态。
例1:
#Barrier 栅栏
import threading,logging
logging.basicConfig(level=logging.INFO,format="[-] %(threadName)s %(message)s") def work(barrier:threading.Barrier):
logging.info("n_waiting = {}".format(barrier.n_waiting)) # 等待的线程数
bid = barrier.wait() # 参与者的id,返回0到线程数减1的数值
logging.info("after barrier {}".format(bid)) # 栅栏之后 barrier = threading.Barrier(3) # 3个参与者,每3个开闸放行,0,1,2 4,5,6 for x in range(1,4): # 所有参数者个数,4,5,6,10,15
threading.Event().wait(1)
threading.Thread(target=work,args=(barrier,),name="Barrier-{}".format(x)).start() 运行结果:
[-] Barrier-1 n_waiting = 0
[-] Barrier-2 n_waiting = 1
[-] Barrier-3 n_waiting = 2
[-] Barrier-3 after barrier 2
[-] Barrier-2 after barrier 1
[-] Barrier-1 after barrier 0
每一个进来就等待,不够3个就阻塞,直到够3个就开闸放行。
Barrier实例的方法:
broken 检测栅栏是否处于打破的状态,返回True或False
abort() 将栅栏置于broken状态,等待中的线程或者调用等待方法的线程都会抛出threading.BrokenBarrieError异常,直到reset方法来恢复栅栏
reset() 恢复栅栏,重新开始拦截
例2:
#Barrier 栅栏
import threading,logging
logging.basicConfig(level=logging.INFO,format="[-] %(threadName)s %(message)s") def work(barrier:threading.Barrier):
logging.info("n_waiting = {}".format(barrier.n_waiting))
try:
bid = barrier.wait()
logging.info("after barrier {}".format(bid))
except threading.BrokenBarrierError:
logging.info("Broken Barrier in {}".format(threading.current_thread())) barrier = threading.Barrier(3) for x in range(1,12): #12个
if x == 3:
barrier.abort() #有一个人坏了规矩
elif x == 6:
barrier.reset()
threading.Event().wait(1)
threading.Thread(target=work,args=(barrier,),name="Barrier-{}".format(x)).start() 运行结果:
[-] Barrier-1 n_waiting = 0 #0,1
[-] Barrier-2 n_waiting = 1
[-] Barrier-2 Broken Barrier in <Thread(Barrier-2, started 3124)>
[-] Barrier-1 Broken Barrier in <Thread(Barrier-1, started 8036)>
[-] Barrier-3 n_waiting = 0
[-] Barrier-3 Broken Barrier in <Thread(Barrier-3, started 7428)>
[-] Barrier-4 n_waiting = 0
[-] Barrier-4 Broken Barrier in <Thread(Barrier-4, started 1828)>
[-] Barrier-5 n_waiting = 0
[-] Barrier-5 Broken Barrier in <Thread(Barrier-5, started 7416)>
[-] Barrier-6 n_waiting = 0 #6,7,8
[-] Barrier-7 n_waiting = 1
[-] Barrier-8 n_waiting = 2
[-] Barrier-8 after barrier 2
[-] Barrier-7 after barrier 1
[-] Barrier-6 after barrier 0
[-] Barrier-9 n_waiting = 0 #9,10,11
[-] Barrier-10 n_waiting = 1
[-] Barrier-11 n_waiting = 2
[-] Barrier-11 after barrier 2
[-] Barrier-9 after barrier 0
[-] Barrier-10 after barrier 1
一共有12个参与者,依次开始,1和2处于等待状态,到达第3的时候,进入了broken状态,则直到第6个,才恢复栅栏,从6开始继续拦截,达到3个(6,7,8)就放行,9,10,11也放行。
例3:
wait方法
#Barrier 栅栏
import threading,logging
logging.basicConfig(level=logging.INFO,format="[-] %(threadName)s %(message)s") def work(barrier:threading.Barrier,i:int):
logging.info("n_waiting = {}".format(barrier.n_waiting))
try:
if i < 3:
bid = barrier.wait(1) #超时1秒就将栅栏置于broken状态,抛出异常后续语句不会执行
else:
if i == 6:
barrier.reset() #恢复栅栏
bid = barrier.wait()
# logging.info("broken status = {}".format(barrier.broken)) #是否处于broken状态
logging.info("after barrier {}".format(bid))
except threading.BrokenBarrierError:
logging.info("Broken Barrier in {}".format(threading.current_thread())) barrier = threading.Barrier(3) for i in range(1,11): #10个
threading.Event().wait(2) #强制延迟2秒,让出时间片
threading.Thread(target=work,args=(barrier,i),name="Barrier-{}".format(i)).start() 运行结果:
[-] Barrier-1 n_waiting = 0
[-] Barrier-1 Broken Barrier in <Thread(Barrier-1, started 3100)>
[-] Barrier-2 n_waiting = 0
[-] Barrier-2 Broken Barrier in <Thread(Barrier-2, started 8836)>
[-] Barrier-3 n_waiting = 0
[-] Barrier-3 Broken Barrier in <Thread(Barrier-3, started 8428)>
[-] Barrier-4 n_waiting = 0
[-] Barrier-4 Broken Barrier in <Thread(Barrier-4, started 1204)>
[-] Barrier-5 n_waiting = 0
[-] Barrier-5 Broken Barrier in <Thread(Barrier-5, started 1556)>
[-] Barrier-6 n_waiting = 0
[-] Barrier-7 n_waiting = 1
[-] Barrier-8 n_waiting = 2
[-] Barrier-8 after barrier 2
[-] Barrier-7 after barrier 1
[-] Barrier-6 after barrier 0
[-] Barrier-9 n_waiting = 0
[-] Barrier-10 n_waiting = 1
阻塞中
wait方法在等待超时1秒后,就强制将栅栏置于broken状态,直到第6个的时候才reset恢复,然后6,7,8放行,9,10,继续阻塞。如果此时有第11个,就会9,10,11放行。
应用场景:
并发初始化
所有线程都必须初始化完成后,才能继续工作,例如运行前加载数据,检查,如果这些工作没完成就不能正常工作运行。
10个线程做10种工作准备,每个线程负责一种工作,只有10个线程都完成后,才能继续工作,先完成的要等待后完成的线程。
例如,启动一个程序,需要先加载磁盘文件、缓存预热、初始化连接池等工作,这些工作可以齐头并进,不过只有都满足了,程序才能继续向后执行。假设数据库链接失败,则初始化工作失败,就要abort,栅栏broken,所有线程收到异常退出。
工作量
有10个计算任务,完成6个,就算工作完成。
PPTBYG
[Python 多线程] Barrier (十一)的更多相关文章
- Python多线程-Barrier(障碍对象)
Barrier(parties, action=None, timeout=None) 每个线程通过调用wait()尝试通过障碍,并阻塞,直到阻塞的数量达到parties时,阻塞的线程被同时全部释放. ...
- Day9 - Python 多线程、进程
Python之路,Day9, 进程.线程.协程篇 本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线 ...
- 搞定python多线程和多进程
1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发 ...
- 浅析Python多线程
学习Python多线程的资料很多,吐槽Python多线程的博客也不少.本文主要介绍Python多线程实际应用,且假设读者已经了解多线程的基本概念.如果读者对进程线程概念不甚了解,可参见知名博主 阮一峰 ...
- python多线程和多进程
1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发 ...
- Python 多线程、进程
本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者 ...
- python 多线程示例
原文链接:http://www.cnblogs.com/whatisfantasy/p/6440585.html 1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的 ...
- Python多线程、进程、协程
本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者 ...
- 转搞定python多线程和多进程
转自https://www.cnblogs.com/whatisfantasy/p/6440585.html 1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的最小 ...
随机推荐
- jQuery 关于IE9上传文件无法进入后台问题的原因及解决办法(ajaxfileupload.js第四弹)
第四弹的诞生完全不在自己最初的计划之中,是有个网友看了先前关于<ajaxfileupload.js系列>的文章后提出的问题,由于自己一直是用chrome浏览器去测试demo,完全忽略IE浏 ...
- [javaSE] 基本数据类型对象包装类
按照java面向对象的原则,每个基本类型都有对应的包装类 byte Byte short Short int Integer long Long boolean Boolean float Float ...
- Java学习--java中的集合框架、Collection接口、list接口
与数组相比:1.数组的长度固定,而集合的长度可变2.数组只能通过下表访问元素,类型固定,而有的集合可以通过任意类型查找所映射的具体对象 java集合框架:collection(list序列,queue ...
- 使用gunzip、tar、rar、(zip压缩和unzip解压缩)
---------------------20171119------------------------------ 解压gz后缀 使用gunzip filename.gz ------------ ...
- Spring MVC 实现Excel的导入导出功能(1:Excel的导入)
简介 这篇文章主要记录自己学习上传和导出Excel时的一些心得,企业办公系统的开发中,经常会收到这样的需求:批量录入数据.数据报表使用 Excel 打开,或者职能部门同事要打印 Excel 文件,而他 ...
- JDBC的DAO设计模式
在javaEE中,java类的属性通过getter和setter来定义,get(或set)方法去除get(set)后,首字母小写即为Java类的属性.操作java类的属性有一个工具包,BeanUtil ...
- drupal7 STMP邮件模块配置
drupal7.54 STMP version = "7.x-1.6" 配置: 注意:上面的“用户名”需要和“站点信息”页面的电子邮件地址保持一致,邮件发送才能成功 ---- ...
- flask多线程多协程操作
local的作用:各个线程各开辟一块空间互不影响 基于local""" import threading from threading import local impo ...
- 3.Bootstrap CSS 概述
1.HTML 5 文档类型(Doctype) Bootstrap 使用了一些 HTML5 元素和 CSS 属性.为了让这些正常工作,您需要使用 HTML5 文档类型(Doctype). 因此,请在使用 ...
- java笔记--增加虚拟机内存
--如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3877243.html "谢谢-- 为避免大型应用程序因虚拟机内存不足而无法 ...