• 多线程必备技能


    前期

    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]
    """
    
  • 相关阅读:
    Log4j appender、layout
    EhCache缓存框架的使用
    Log4j rootLogger根配置以及4种日志级别
    开发chrome 插件, background.js中 console log 看不到解决方法
    Windows cmd 长时间不输出新内容 直到按下ctrl + c 取消或者回车的解决办法
    如何查看当前分支从哪个支线创建而来
    C# 获取相对路径的字符串
    解决adobe air sdk打包 apk后自动在包名前面加上air. (有个点)前缀的问题
    sublime text 输入法候选词不跟随光标
    Windows 批处理设置dns ,解决能上qq不能开网页
  • 原文地址:https://www.cnblogs.com/BenLam/p/12752389.html
Copyright © 2020-2023  润新知