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 (十一)的更多相关文章

  1. Python多线程-Barrier(障碍对象)

    Barrier(parties, action=None, timeout=None) 每个线程通过调用wait()尝试通过障碍,并阻塞,直到阻塞的数量达到parties时,阻塞的线程被同时全部释放. ...

  2. Day9 - Python 多线程、进程

    Python之路,Day9, 进程.线程.协程篇   本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线 ...

  3. 搞定python多线程和多进程

    1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发 ...

  4. 浅析Python多线程

    学习Python多线程的资料很多,吐槽Python多线程的博客也不少.本文主要介绍Python多线程实际应用,且假设读者已经了解多线程的基本概念.如果读者对进程线程概念不甚了解,可参见知名博主 阮一峰 ...

  5. python多线程和多进程

    1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发 ...

  6. Python 多线程、进程

    本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者 ...

  7. python 多线程示例

    原文链接:http://www.cnblogs.com/whatisfantasy/p/6440585.html 1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的 ...

  8. Python多线程、进程、协程

    本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者 ...

  9. 转搞定python多线程和多进程

    转自https://www.cnblogs.com/whatisfantasy/p/6440585.html 1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的最小 ...

随机推荐

  1. xshell ssh连接linux时提示ssh服务器拒绝了密码

    用Xshell root连接时显示ssh服务器拒绝了密码,应该是应该是sshd的设置不允许root用户用密码远程登录 修改 /etc/ssh/sshd_config文件,注意,安装了openssh才会 ...

  2. HttpServletRequest 各种方法总结(转)

    HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息. 转自: ...

  3. C# 调用C/C++动态链接库,结构体中的char*类型

    用C#掉用C++的dll直接import就可以之前有不同的类型对应,当要传递结构体的时候就有点麻烦了,这里有一个结构体里边有char*类型,这个类型在C#中调用没法声明,传string是不行的默认st ...

  4. 浏览器组成、线程及event loop

    浏览器组成 User interface: a. Every part of the browser display, except the window. b. The address bar, b ...

  5. 从接口取到的JSON数据如何导入进本地SQL数据库

    新手学习,求大神指点. 首先:在数据库建立表--设计字段(最好和接口说明文档里面的一致) 第一步:获取接口中的字符串:这里获取的是有转义字符的字符串 HttpWebRequest request = ...

  6. FineReport如何手动推送APP消息

    在报表填报成功后,发送消息至APP会提示数据已更新.再次期间用户需要有查看该模板的权限,如果没有的话,则无法接受到提示信息.那么在FineReport移动端中,如何手动推送APP消息呢? 具体用法 在 ...

  7. LeetCode 1. Two Sum (JavaScript)

    1. Two Sum Given an array of integers, return indices of the two numbers such that they add up to a ...

  8. 7.bootstrap HTML编码规范

    Bootstrap HTML编码规范 语法 用两个空格来代替制表符(tab) -- 这是唯一能保证在所有环境下获得一致展现的方法. 嵌套元素应当缩进一次(即两个空格). 对于属性的定义,确保全部使用双 ...

  9. Oracle常用名词解释

    好久没做rac,最近要做架构梳理,这里针对Oracle常用的名词缩写,这里做个记录,希望对大家有所帮助. RAC 全称是Real Application Cluster,oracle的高可用群集,即实 ...

  10. eclipse直接使用tomcat安装程序的webapp目录调试

    感谢此文:http://blog.csdn.net/soszou/article/details/23673133 本文很多技术及操作来源于此文 需求:因为微信方面的开发调试.为了测试方便,直接构建了 ...