多线程必备技能

前期

  1. Queue模块提供了同步线程安全的队列类,包括:
    FIFO (先入先出)队列 Queue
    LIFO (后入先出)队列 LifoQueue
    优先队列 PriorityQueue
    这些队列都提供了锁,可以直接使用队列来实现线程间的同步
  2. 反正就是给我这种小白写多线程中直接使用就好了

Queue 常用模块

queue.Queue(maxsize=0)				# FIFO, 如果maxsize小于1就表示队列长度无限
queue.LifoQueue(maxsize=0)			# LIFO, 如果maxsize小于1就表示队列长度无限
queue.qsize()						# 返回队列的大小
queue.empty()						# 如果队列为空,返回True,反之False
queue.full()						# 如果队列满了,返回True,反之False,Queue.full 与 maxsize 大小对应
queue.put(item, [block[, timeout]])	# 写队列,timeout等待时间 
queue.get([block[, timeout]])		# 获取队列,timeout等待时间
queue.get_nowait()					# 相当于Queue.get(False),非阻塞方法
queue.queue.clear()					# 清空队列
queue.join()     					# 阻塞调用线程,直到队列中的所有任务被处理掉
queue.task_done()					# 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
									# 每个get()调用得到一个任务,接下来task_done()调用告诉队列该任务已经处理完毕。

queue 写入与读取

# !/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2020/4/22 9:54
# @File    : Queue.py
# @Link    : https://www.cnblogs.com/BenLam/

from queue import Queue
from queue import LifoQueue

def test():
    q = Queue()
    for i in range(6):
        q.put(i)

    while not q.empty():
        print(q.get())
test()

"""
打印:
    0
    1
    2
    3
    4
    5
"""

def test():
    q = LifoQueue()
    for i in range(6):
        q.put(i)

    while not q.empty():
        print(q.get())
test()

"""
打印:
    5
    4
    3
    2
    1
    0
"""

Queue 例子

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2020/4/22 9:54
# @File    : Queue_test.py
# @Author  : BenLam
# @Link    : https://www.cnblogs.com/BenLam/
# @Version : PyCharm

from queue import Queue,LifoQueue,PriorityQueue
from queue import deque

#先进先出队列
q = Queue(maxsize=10)

#后进先出队列
lq = LifoQueue(maxsize=11)

#优先级队列
pq = PriorityQueue(maxsize=10)

for _ in range(10):
    q.put(_)
    lq.put(_)
    pq.put(_)

print("先进先出队列: %s ;是否为空: %s ;多大, %s ;是否满, %s" %(q.queue,q.empty(),q.qsize(),q.full()))
print("后进先出队列: %s ;是否为空: %s ;多大, %s ;是否满, %s" %(lq.queue,lq.empty(),lq.qsize(),lq.full()))
print("优先级队列:  %s ;是否为空: %s ,多大, %s ;是否满, %s " %(pq.queue,pq.empty(),pq.qsize(),pq.full()))

print(f" q: {q.get()} 
lq: {lq.get()} 
pq: {pq.get()}")

print("先进先出队列: %s ;是否为空: %s ;多大, %s ;是否满, %s" %(q.queue,q.empty(),q.qsize(),q.full()))
print("后进先出队列: %s ;是否为空: %s ;多大, %s ;是否满, %s" %(lq.queue,lq.empty(),lq.qsize(),lq.full()))
print("优先级队列: %s ;是否为空: %s ,多大, %s ;是否满, %s" %(pq.queue,pq.empty(),pq.qsize(),pq.full()))

# === === === === === === === === === === === ===
print("=== === 双端队列 === ===")
dq=deque(['1','2'])
print(dq)
dq.append('c')
print(dq)
print(dq.pop())
print(dq)
print(dq.popleft())
print(dq)
dq.appendleft('d')
print(dq)
print(len(dq))
print("=== === 双端队列 结束 === ===")
"""
打印:
    先进先出队列: deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) ;是否为空: False ;多大, 10 ;是否满, True
    后进先出队列: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] ;是否为空: False ;多大, 10 ;是否满, False
    优先级队列:  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] ;是否为空: False ,多大, 10 ;是否满, True
         q: 0
        lq: 9
        pq: 0
    先进先出队列: deque([1, 2, 3, 4, 5, 6, 7, 8, 9]) ;是否为空: False ;多大, 9 ;是否满, False
    后进先出队列: [0, 1, 2, 3, 4, 5, 6, 7, 8] ;是否为空: False ;多大, 9 ;是否满, False
    优先级队列: [1, 3, 2, 7, 4, 5, 6, 9, 8] ;是否为空: False ,多大, 9 ;是否满, False
    === === 双端队列 === ===
        deque(['1', '2'])
        deque(['1', '2', 'c'])
            c
        deque(['1', '2'])
            1
        deque(['2'])
        deque(['d', '2'])
            2
    === === 双端队列 结束 === ===
    [Finished in 0.6s]
"""

生产消费者

  • 生产消费者就是 → 生产者/消费者模式,反正我们就叫它为:生肖(生消)
  • 生消并非 GOF 自带模式,不知道 GOF 可以参考我另一篇笔记《2020年 - 在家学习汇总》
  • | 【 生产者 】 → → → [ 缓冲区 ] → → → 【 消费者 】
  • 生产者 - 负责产生数据,放入缓冲区
  • 消费者 - 负责缓冲区取值并处理
  • 优点:
    • 解耦
      1. 缓冲区的存在可以让他俩降低互相之间的依赖性,老产修改代码不影响老消
    • 并发
      1. 他俩不是直接调用,而是两个独立的个体,可以说老产把数据摊牌在缓冲区完事了;
      2. 老消又不用跪着向想他要饭,直接从缓冲区取数据就好了;
      3. 参考(饭堂阿姨把饭菜+饭勺放在桌上,再也不怕阿姨帕金森模式)

生消例子

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2020/4/22 9:54
# @File    : PC_test.py
# @Author  : BenLam
# @Link    : https://www.cnblogs.com/BenLam/
# @Version : PyCharm

import queue
import threading

def Produce(name):
    count = 0
    while count < 5:
        count += 1
        print(f"{name} 已经做好了第 {count} 双皮鞋, - 皮鞋搞完,把妹去")
        q.put(count)
        q.join()  # 等待接收信号

def Consumer(name):
    count = 0
    while count < 5:
        data = q.get()
        # print(f"{name} 即将囤货......")
        q.task_done()
        print(f"{name} 已经把 {data} 双皮鞋买了...")
        count += 1

if __name__ == '__main__':
    q = queue.Queue()
    A = threading.Thread(target=Produce, args=("皮革厂老板 - ",))
    B = threading.Thread(target=Consumer, args=("A - ",))
    C = threading.Thread(target=Consumer, args=("B - ",))
    D = threading.Thread(target=Consumer, args=("C - ",))

    A.setDaemon(True)
    A.start()
    B.start()
    C.start()
    D.start()

"""
打印:
    皮革厂老板 -  已经做好了第 1 双皮鞋, - 皮鞋搞完,把妹去
    A -  已经把 1 双皮鞋买了...
    皮革厂老板 -  已经做好了第 2 双皮鞋, - 皮鞋搞完,把妹去
    B -  已经把 2 双皮鞋买了...
    皮革厂老板 -  已经做好了第 3 双皮鞋, - 皮鞋搞完,把妹去
    皮革厂老板 -  已经做好了第 4 双皮鞋, - 皮鞋搞完,把妹去
    C -  已经把 3 双皮鞋买了...
    A -  已经把 4 双皮鞋买了...
    皮革厂老板 -  已经做好了第 5 双皮鞋, - 皮鞋搞完,把妹去
    B -  已经把 5 双皮鞋买了...
[Cancelled]
"""
原文地址:https://www.cnblogs.com/BenLam/p/12752389.html