zoukankan      html  css  js  c++  java
  • 生产者消费者模型 开启线程的两种方式 多线程与多进程开启速度区别 线程进程pid 统一进程内线程是共享数据的 线程的其他方法 join与守护线程 互斥锁

    生产者消费者模型

    进程:

    ​ 生产者消费者模型

    ​ 编程思想, 模型, 设计模式, 理论等等, 都是交给你一种编程的方法, 以后遇到类似的情况, 套用即可

    生产者消费者模型三要素

    ​ 生产者: 产生数据的

    ​ 消费者: 接收数据做进一步处理的

    ​ 容器: 盆(队列)

    队列容器的作用

    ​ 起到缓冲的作用, 平衡生产力与消费力, 解耦

    实例

    import time
    import random
    from multiprocessing import Process, Queue
    
    
    def producer(q, name):
        for i in range(1, 6):
            time.sleep(random.randint(1, 2))
            res = f"{i}号包子"
            q.put(res)
            print(f"生产者{name} 生产了{res}")
    
    
    def consumer(q, name):
        while 1:
            try:
                food = q.get(timeout=3)
                time.sleep(random.randint(1, 3))
                print(f"33[31;0m 消费者{name} 吃了{food} 33[0m")
            except Exception:
                return
    
    
    if __name__ == '__main__':
        q = Queue()
    
        p1 = Process(target=producer, args=(q, "孙宇"))
        p2 = Process(target=consumer, args=(q, "海狗"))
    
        p1.start()
        p2.start()
    
    """
    生产者孙宇 生产了1号包子
    生产者孙宇 生产了2号包子
     消费者海狗 吃了1号包子 
    生产者孙宇 生产了3号包子
     消费者海狗 吃了2号包子 
    生产者孙宇 生产了4号包子
    生产者孙宇 生产了5号包子
     消费者海狗 吃了3号包子 
     消费者海狗 吃了4号包子 
     消费者海狗 吃了5号包子 
    """
    

    开启线程的两种方式

    进程是资源单位, 线程是执行单位

    什么是线程

    ​ 一条流水线的工作流程.

    进程:

    ​ 在内存中开启一个进程空间, 然后将主进程的所有的资源数据复制一份, 然后调用CPU去执行这些代码

    具体描述进程:

    ​ 在内存中开启一个进程空间, 然后将主进程的所有的资源数据复制一份, 然后调用线程去执行代码

    执行流程

    ​ 主线程子线程没有地位之分, 但是一个主线程在执行, 执行完, 要等待其他非守护子线程执行完之后, 才能结束主线程, 结束本进程

    # 第一种方式
    from threading import Thread
    import time
    
    
    def task(name):
        print(f"{name} is running")
        time.sleep(1)
        print(f"{name} is gone")
    
    
    if __name__ == '__main__':
    
        t1 = Thread(target=task, args=("海狗",))
        t1.start()
        print("===主线程")
        # 线程没有主次之分
    """
    李业 is running
    ===主线程
    李业 is gone
    """
        
    # 第二种方式
    from threading import Thread
    import time
    
    class MyThread(Thread):
    
        def __init__(self, name, l1, s1):
            super(MyThread, self).__init__()
            self.name = name
            self.l1 = l1
            self.s1 = s1
    
        def run(self):
            print(f"{self.name} is running")
            time.sleep(1)
            print(f"{self.name} is gone")
    
    
    if __name__ == '__main__':
        t1 = MyThread("李业", [1,2,3], "180")
        t1.start()
        print("===主线程")
    """
    李业 is running
    ===主线程
    李业 is gone
    """
    

    多线程与多进程开启速度区别

    from multiprocessing import Process
    import time
    
    
    def work():
        print("hello")
    
    
    if __name__ == '__main__':
        start_time = time.time()
        lst = []
        for i in range(10):
            t = Process(target=work)
            t.start()
            lst.append(t)
        for i in lst:
            i.join()
        print(time.time() - start_time)
    """
    hello
    hello
    hello
    hello
    hello
    hello
    hello
    hello
    hello
    hello
    1.004307746887207
    """
    
    
    # 多线程
    from threading import Thread
    import time
    
    
    def task():
        print("hello")
    
    
    if __name__ == '__main__':
        start_time = time.time()
        lst = []
        for i in range(10):
            t = Thread(target=task)
            t.start()
            lst.append(t)
        for i in lst:
            i.join()
        print(time.time() - start_time)
    """
    hello
    hello
    hello
    hello
    hello
    hello
    hello
    hello
    hello
    hello
    0.0019998550415039062
    """
    

    ​ 开启进程的开销非常大, 比开启线程的开销大很多.

    ​ 开启线程的速度非常快, 要快几十倍到上百倍.

    线程进程pid

    # 进程pid
    from multiprocessing import Process
    import os
    
    def task():
        print(f"子进程:{os.getpid()}")
        print(f"主进程:{os.getppid()}")
    
    if __name__ == '__main__':
        p1 = Process(target=task)
        p2 = Process(target=task)
        p1.start()
        p2.start()
        print(f"==主:{os.getpid()}")
    """
    ==主:51060
    子进程:51128
    主进程:51060
    子进程:42856
    主进程:51060
    """
    
    # 线程pid
    from threading import Thread
    import os
    
    def task():
        print(os.getpid())
    
    if __name__ == '__main__':
        t = Thread(target=task)
        t1 = Thread(target=task)
        t.start()
        t1.start()
        print(f"===主线程:{os.getpid()}")
    """
    51768
    51768
    ===主线程:51768
    """
    # 多线程在同一个进程内, 所以pid都一样
    

    同一进程内线程是共享数据的

    ​ 线程与线程之间可以共享数据, 进程与进程之间需要借助队列等方法实现通信

    ​ 同一进程内的资源数据对于这个进程内的多个线程来说是共享的

    线程的应用

    ​ 并发: 一个CPU看起来像是同时执行多个任务

    ​ 单个进程开启三个线程, 并发的执行任务

    ​ 开启三个进程并发的执行任务

    ​ 文本编辑器:

    ​ 1.输入文字

    ​ 2.在屏幕上显示

    ​ 3.保存在磁盘中

    ​ 开启多线程就非常简单了:

    ​ 数据共享, 开销小, 速度快

    from threading import Thread
    
    
    x = 3
    
    def task():
        global x
        x = 100
    
    
    if __name__ == '__main__':
        t1 = Thread(target=task)
        t1.start()
        t1.join()
        print(f"===主线程{x}")
        
    """
    ===主线程100
    """
    

    线程的其他方法

    from threading import Thread, current_thread, enumerate, activeCount
    import os
    import time
    
    x = 3
    def task():
        time.sleep(1)
        print(666)
    
    
    if __name__ == '__main__':
        t1 = Thread(target=task)
        t2 = Thread(target=task)
        t1.start()
        t2.start()
        print(t1.isAlive())    # 判断子线程是否存活
        print(t1.getName())	   # 获取子线程名字
        t1.setName("子进程-1")  # 修改子线程名字
        print(t1.name)          # 获取子线程的名字 ***
        print(current_thread())  # 获取当前线程的内容
        print(enumerate())      # 获取当前进程下的所有线程,以列表形式展示
        print(activeCount())   # 获取当前进程下的所有存活线程的数量
        print(os.getpid())  
        
    """
    True
    Thread-1
    子进程-1
    <_MainThread(MainThread, started 60668)>
    [<_MainThread(MainThread, started 60668)>, <Thread(子进程-1, started 55172)>, <Thread(Thread-2, started 62068)>]
    3
    61048
    666
    666
    """
    

    join 与 守护线程

    守护线程, 等待非守护子线程以及主线程结束之后, 结束

    from threading import Thread
    import time
    
    def say_hi(name):
        print("你滚")
        time.sleep(2)
        print(f"{name} say hello")
    
    if __name__ == '__main__':
        t = Thread(target=say_hi, args=("egon",))
        # t.setDaemon(True)      # 必须在t.start()前设置, 两种方法都可以
        t.daemon = True
        t.start()
        print("主线程")        # 注意 线程的开启速度比进程要快的多
        
    """
    你滚
    主线程
    """
    
    from threading import Thread
    import time
    
    def foo():
        print(123)  
        time.sleep(1)
        print("end123")  
    
    def bar():
        print(456)  
        time.sleep(3)
        print("end456")  
    
    
    t1=Thread(target=foo)
    t2=Thread(target=bar)
    
    t1.daemon=True
    t1.start()
    t2.start()
    print("main-------")  
    
    """
    123
    456
    main-------
    end123
    end456
    """
    

    互斥锁

    from threading import Thread
    import time
    import random
    x = 100
    
    def task():
        global x
        temp = x
        time.sleep(random.randint(1, 3))
        temp = temp - 1
        x = temp
    
    
    if __name__ == '__main__':
        l1 = []
        for i in range(100):
            t = Thread(target=task)
            l1.append(t)
            t.start()
    
        for i in l1:
            i.join()
        print(f'主线程{x}')
    """
    主线程99
    """
    # 多个任务共抢一个数据, 为了保证数据的安全性, 要让其串行
    
    
    from threading import Thread
    from threading import Lock
    import time
    x = 100
    
    def task(lock):
    
        lock.acquire()
        global x
        temp = x
        temp = temp - 1
        x = temp
        lock.release()
    
    
    if __name__ == '__main__':
        mutex = Lock()
        l1 = []
        for i in range(100):
            t = Thread(target=task,args=(mutex,))
            l1.append(t)
            t.start()
    
        time.sleep(3)
        print(f'主线程{x}')
    """
    主线程0
    """
    
  • 相关阅读:
    jQuery插件开发的模式和结构
    jQuery插件开发详细教程
    一个JavaScript Function Outliner插件 第三个版本 让你的JavaScript代码也支持折叠
    web开发过程中经常用到的一些公共方法及操作
    C#操作注册表
    EventBus使用详解(一)——初步使用EventBus
    android xml布局文件中tools:layout的作用
    调用android系统相机拍照并保存
    Android组件间通信库EventBus学习
    网络通信框架Volley使用详细说明
  • 原文地址:https://www.cnblogs.com/beichen123/p/11397807.html
Copyright © 2011-2022 走看看