目录
Python 多线程编程目录
Python 多线程编程-01-threading 模块初识
Python 多线程编程-02-threading 模块-锁的使用
Python 多线程编程-03-threading 模块 - Condition
Python 多线程编程-04-threading 模块 - Event
Python 多线程编程-05-threading 模块 - Semaphore 和 BoundedSemaphore
Python 多线程编程-06-threading 模块 - Timer
Python 多线程编程-07-threading 模块 - Barrier
1. threading.Barrier
1.1 threading.Barrier 作用
Barrier 即栅栏的意思,可以想象成路障、道闸,它是 Python 3.2 引入的新功能。
在 Python 多线程编程-05-threading 模块 - Semaphore 和 BoundedSemaphore 中曾经提过,使用 Semaphore 或者是 BoundedSemaphore 可以控制线程的最多数量。threading.Barrier 也可以起到控制线程的作用,但它不是控制上限,而是控制下限,即满足到一定数量才能进行。
具体机制:
每个线程通过调用 wait() 尝试通过 Barrier,如果不能通过,则阻塞;直到阻塞的线程数量达到了 parties 时候,阻塞的线程被全部释放。如果 Barrier 里面设置了 timeout,那么阻塞时间超过 timeout 时候则报错。
1.2 threading.Barrier 构造函数
1.2.1 threading.Barrier 构造方法
threading.Barrier 的构造方法如下:
barrier = Barrier(parties, action=None, timeout=None)
1.2.2 threading.Barrier 参数列表
- parties:控制的线程数,即设置的 Barrier 能够通过的线程数最小值;
- action:是一个可调用函数,当等待的线程到达了线程障碍数量 parties,其中一个线程会首先调用 action 对应函数,之后再执行线程自己内部的代码;
- timeout:默认的超时时间
1.3 threading.Barrier 属性和方法
序号 | 属性和方法 | 描述 |
1 | 方法 abort() | 将障碍置为断开状态,这将导致已调用 wait() 或之后调用 wait() 的线程触发 BrokenBarrierError |
2 | 属性 broken | 布尔值,刚刚创建 barrier 时候barrier.broken 为 False,如果调用了 barrier.abort(),barrier.broken 则为 True |
3 | 属性 n_waiting | 当前在屏障中等待的线程数,一般在 wait() 方法前可能为非 0, wait() 方法成功后为 0 |
4 | 属性 parties | 通过障碍所需的线程数。 |
5 | 方法 reset() | 重置该 Barrier 回初始状态;所有正在 wait() 的线程会得到 BrokenBarrier exception。 |
6 | 方法wait(timeout=None) | 每个线程通过调用 wait() 尝试通过 Barrier,如果不能通过,则阻塞;直到阻塞的线程数量达到了 parties 时候,阻塞的线程被全部释放。如果 Barrier 里面设置了 timeout,那么阻塞时间超过 timeout 时候则报错。 |
1.4 threading.Barrier 使用示范
1.4.1 简单的控制同时运行的线程数量
设计了一段代码,只有满足了三个线程才会通过 Barrier,而我只给了5个线程,所以可以看到,前面三个线程得到了执行,后面的两个线程都在持续等待中。
import threading
import time
words=["a","12","你好!","春风十里","一起向未来"]
thread_list=[]
barrier=threading.Barrier(3)
def show_time(word):
print("Coming in show time ==>",word)
barrier.wait()
print(time.ctime()+"==>"+word)
for word in words:
t=threading.Thread(target=show_time,args=(word,))
thread_list.append(t)
for thread in thread_list:
thread.start()
for thread in thread_list:
thread.join()
print(time.ctime()+" All done!")
运行结果:
如果线程数调整为 6 那么后面三个线程也会被执行。
import threading
import time
words=["a","12","你好!","春风十里","一起向未来","结束了"]
thread_list=[]
barrier=threading.Barrier(3)
def show_time(word):
print("Coming in show time ==>",word)
barrier.wait()
print(time.ctime()+"==>"+word)
for word in words:
t=threading.Thread(target=show_time,args=(word,))
thread_list.append(t)
for thread in thread_list:
thread.start()
for thread in thread_list:
thread.join()
print(time.ctime()+" All done!")
运行结果
从上面的运行结果也可以看出,虽然所有的线程都被执行了,但是同一批线程彼此之间执行的顺序是不确定的。
1.4.2 使用 timeout 控制等待时间
从 1.4.1 可以看到,如果迟迟没有等待足够的线程,部分程序可能会一直阻塞,这时候需要一定的 timeout 机制,来阻止这种无休止的等待。
只需要修改 barrier.wait 方法就可以,加入timeout 参数为4,即最多等待 4秒。
代码修改如下:
words=["a","12","你好!","春风十里","一起向未来"]
thread_list=[]
barrier=threading.Barrier(3)
def show_time(word):
print("Coming in show time ==>",word)
barrier.wait(4)
print(time.ctime()+"==>"+word)
for word in words:
t=threading.Thread(target=show_time,args=(word,))
thread_list.append(t)
for thread in thread_list:
thread.start()
for thread in thread_list:
thread.join()
print(time.ctime()+" All done!")
运行结果如下,当超时后,就会报错 “threading.BrokenBarrierError”
可以使用 try 机制来避免程序中断。
words=["a","12","你好!","春风十里","一起向未来"]
thread_list=[]
barrier=threading.Barrier(3)
def show_time(word):
print("Coming in show time ==>",word)
try:
barrier.wait(4)
print(time.ctime()+"==>"+word)
except threading.BrokenBarrierError:
print("The threading is time out and the word {0} will not be shown!".format(word))
for word in words:
t=threading.Thread(target=show_time,args=(word,))
thread_list.append(t)
for thread in thread_list:
thread.start()
for thread in thread_list:
thread.join()
print(time.ctime()+" All done!")
运行结果如下:
这个 timeout 也可以在构造 Barrier 时候就设置,就不需要在调用 wait()方法时候再设置了。
如果 Barrier 在构建时候设置了 timeout ,在调用 wait() 方法时候也设置了不同的 timeout 参数,那么以 wait() 时候为准。
words=["a","12","你好!","春风十里","一起向未来"]
thread_list=[]
barrier=threading.Barrier(3,timeout=4)
def show_time(word):
print("Coming in show time ==>",word)
try:
barrier.wait(5)
print(time.ctime()+"==>"+word)
except threading.BrokenBarrierError:
print("The threading is time out and the word {0} will not be shown!".format(word))
for word in words:
t=threading.Thread(target=show_time,args=(word,))
thread_list.append(t)
for thread in thread_list:
thread.start()
for thread in thread_list:
thread.join()
print(time.ctime()+" All done!")
运行结果如下:
1.4.3 使用 Barrier 中的 action 参数
使用 Barrier 中的 action 参数,可以在每次放过一批线程时候做一些操作。
import threading
import time
words=["a","12","你好!","春风十里","一起向未来","最后一个"]
show_time_list=[]
class Show_Time(threading.Thread):
def __init__(self,barrier,word=None):
super().__init__()
self.barrier=barrier
self.word=word
def run(self):
self.barrier.wait()
print(time.ctime()+"==>"+self.word)
def ok():
print("I am OK!")
barrier=threading.Barrier(3,action=ok)
for word in words:
t=Show_Time(barrier,word)
show_time_list.append(t)
for thread in show_time_list:
thread.start()
for thread in show_time_list:
thread.join()
print(time.ctime()+" All done!")
运行结果如下:
'''
要是大家觉得写得还行,麻烦点个赞或者收藏吧,想个博客涨涨人气,非常感谢!
'''