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. jQuery 关于IE9上传文件无法进入后台问题的原因及解决办法(ajaxfileupload.js第四弹)

    第四弹的诞生完全不在自己最初的计划之中,是有个网友看了先前关于<ajaxfileupload.js系列>的文章后提出的问题,由于自己一直是用chrome浏览器去测试demo,完全忽略IE浏 ...

  2. [javaSE] 基本数据类型对象包装类

    按照java面向对象的原则,每个基本类型都有对应的包装类 byte Byte short Short int Integer long Long boolean Boolean float Float ...

  3. Java学习--java中的集合框架、Collection接口、list接口

    与数组相比:1.数组的长度固定,而集合的长度可变2.数组只能通过下表访问元素,类型固定,而有的集合可以通过任意类型查找所映射的具体对象 java集合框架:collection(list序列,queue ...

  4. 使用gunzip、tar、rar、(zip压缩和unzip解压缩)

    ---------------------20171119------------------------------ 解压gz后缀 使用gunzip filename.gz ------------ ...

  5. Spring MVC 实现Excel的导入导出功能(1:Excel的导入)

    简介 这篇文章主要记录自己学习上传和导出Excel时的一些心得,企业办公系统的开发中,经常会收到这样的需求:批量录入数据.数据报表使用 Excel 打开,或者职能部门同事要打印 Excel 文件,而他 ...

  6. JDBC的DAO设计模式

    在javaEE中,java类的属性通过getter和setter来定义,get(或set)方法去除get(set)后,首字母小写即为Java类的属性.操作java类的属性有一个工具包,BeanUtil ...

  7. drupal7 STMP邮件模块配置

    drupal7.54 STMP  version = "7.x-1.6" 配置:   注意:上面的“用户名”需要和“站点信息”页面的电子邮件地址保持一致,邮件发送才能成功 ---- ...

  8. flask多线程多协程操作

    local的作用:各个线程各开辟一块空间互不影响 基于local""" import threading from threading import local impo ...

  9. 3.Bootstrap CSS 概述

    1.HTML 5 文档类型(Doctype) Bootstrap 使用了一些 HTML5 元素和 CSS 属性.为了让这些正常工作,您需要使用 HTML5 文档类型(Doctype). 因此,请在使用 ...

  10. java笔记--增加虚拟机内存

    --如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3877243.html "谢谢-- 为避免大型应用程序因虚拟机内存不足而无法 ...