zoukankan      html  css  js  c++  java
  • 线程,生产者消费者模型

    什么是线程:
    1.线程是cpu最小的执行单位
    2.进程是资源单位
    3.如果将操作系统比作工厂的话,进程是车间,线程是流水线,而cpu为电源
    开启一个进程默认有一个线程即主线程

    多线程的好处:①当遇到IO操作时,可以将主进程分为多个线程,cpu遇到IO可能会切换到该进程的其他线程,cpu在线程间切换,
    故拥有就绪态多的线程的进程被执行的概率变高,提升了进程的效率

    线程的两种开启方式:①实例化Thread类②自定义MYthread类,继承Thread类,覆盖run方法

    什么时候需要开启多线程,什么时候需要开启多进程:
    ①当我们只有1个cpu即单核:
    进程对于操作系统的资源耗费非常高,而线程相反会场低(比进程低10-100倍),只有一个cpu的话,开启多线程要比多进程效率更高
    ②当我们有多个cpu
    1.当我们的多进程都是IO时间较长时,开启多进程和多线程没有差别,因为CPU遇到IO都会切换,IO等待较长时,多进程和多线程都可以在等待时间内将其他非IO程序完成
    2.当我们的多进程都cpu密集型,即运算多时,多进程要比多线程运算的快

    同一个进程的多个线程是共享资源的
    也就是说当我们多个线程对共有的资源修改时会导致数据的错乱,故需要线程互斥锁来保证数据安全,使用方法与进程锁一样

    守护线程:
    因为线程是共享数据资源的,为了保证数据安全,主线程会在所有子线程执行完毕后结束,故主线程的守护线程会在所有非守护线程执行完毕后结束

    信号量:
    semaphore
    互斥锁是一个种特殊的信号量,即数量限制为1,
    信号量同一时刻可以允许规定数量的程序同时共享数据

    生产者与消费者模型问题:
    消费者不知道生产者何时生产完毕,一直在取容器中的产品消费,当生产者不再生产时,消费者会一直处于阻塞状态
    解决方法
    ①生产者在容器中放入None标记,当消费者获取到None标记时,则停止从容器中取产品
    并发的起动,但生产者要优先生产完毕,并根据消费者数量放入等额的None即停止标记

    from threading import Thread
    import time,random
    from multiprocessing import Queue
    q = Queue()
    
    def producter(name):
        for i in range(5):
            time.sleep(random.randint(1,2))
            res = "%s的第%s个包子"%(name,i+1)
            print("%s生产了第%s个包子"%(name,i+1))
            q.put(res)
    
    def customer(name):
        while True:
            time.sleep(random.randint(1,2))
            res = q.get()
            if not res :break
            print("%s正在吃%s"%(name,res))
    if __name__ == '__main__':
        p1 = Thread(target=producter,args = ("zb",))
        p2 = Thread(target=producter,args = ("xzh",))
        p3 = Thread(target=producter,args = ("lqq",))
        c1 = Thread(target=customer,args = ("egon",))
        c2 = Thread(target=customer,args = ("alex",))
        p1.start()
        p2.start()
        p3.start()
        c1.start()
        c2.start()
        p1.join()
        p2.join()
        p3.join()
        q.put(None)
        q.put(None)
    

    ②使用可join的队列即JoinableQueue
    同理:让生产者优先级提高,先告知q.join()总产品的数量,当消费者获取时产品,q.task_done(),给q.join()发一个通知,
    当数量吻合时,q.join()执行完毕,则主线程执行完毕,将消费者设置为主线程的守护线程,则消费者同时挂掉,不会再去获取

    from threading import Thread
    import time,random
    from multiprocessing import JoinableQueue
    q = JoinableQueue()
    
    def producter(name):
        for i in range(5):
            time.sleep(random.randint(1,2))
            res = "%s的第%s个包子"%(name,i+1)
            print("%s生产了第%s个包子"%(name,i+1))
            q.put(res)
    
    def customer(name):
        while True:
            time.sleep(random.randint(1,2))
            res = q.get()
            if not res :break
            print("%s正在吃%s"%(name,res))
            q.task_done()
    if __name__ == '__main__':
        p1 = Thread(target=producter,args = ("zb",))
        p2 = Thread(target=producter,args = ("xzh",))
        p3 = Thread(target=producter,args = ("lqq",))
        c1 = Thread(target=customer,args = ("egon",))
        c2 = Thread(target=customer,args = ("alex",))
        p1.start()
        p2.start()
        p3.start()
        c1.daemon =True
        c1.start()
        c2.daemon = True
        c2.start()
        p1.join()
        p2.join()
        p3.join()
        q.join()
    
  • 相关阅读:
    set集合
    作业(2)
    字典
    列表功能
    字符串
    while循环
    pb加密转换成C#
    NET在64位系統使用32位oracle客户端访问数据库
    SQL Server中查找包含某个文本的存储过程
    SQLServer 错误: 15404,无法获取有关 Windows NT 组/用户
  • 原文地址:https://www.cnblogs.com/robert-zhou/p/10211222.html
Copyright © 2011-2022 走看看