zoukankan      html  css  js  c++  java
  • Python入门学习-DAY35-线程

    一、进程补充

    1.进程间通信(IPC机制)

    进程间通讯有两种方法:管道或者队列。

    1 队列和管道都是将数据存放于内存中

    2 队列又是基于(管道+锁)实现的,可以让我们从复杂的锁问题中解脱出来。

            

    from multiprocessing import Queue
    
    q=Queue(3)#3是队列允许存在的个数
    q.put('1')
    q.put('2')
    q.put('3')
    
    
    
    print(q.get(block=True,timeout=2))
    print(q.get())
    print(q.get())

    block默认是True,意思是可以阻塞。timeout是阻塞时间,阻塞时间到了会报错

    那么什么情况下会阻塞:

    1.当限制队列里的数量时,放入超过限制的消息,会阻塞,等待第一个放入的被取走,才会继续执行

    2.当限制队列里的数量时,取出超过限制的消息,因为此时的队列是空的,只有队列里再次放入内容时才会继续执行

    2.生产者消费者模型

    1. 什么是生产者消费者模型

      生产者:代指生产数据的任务
      消费者:代指处理数据的任务
      该模型的工作方式:
        生产生产数据传递消费者处理

      实现方式:
        生产者---->队列<------消费者

    2. 为何要用

    当程序中出现明细的两类任务,一类负责生产数据,一类负责处理数据
    就可以引入生产者消费者模型来实现生产者与消费者的解耦合,平衡生产能力与消费能力,从提升效率

    3. 如何用

    from multiprocessing import  Process,Queue
    import time,random
    
    def producer(name,food,p):
        for i in range(3):
            res='%s%s'%(food,i)
            time.sleep(random.randint(1,3))
            print('%s生产了%s'%(name,res))
            p.put(res)
    
    def customer(name,p):
        while True:
            res=p.get()
            if res is None:break#判断消费者是否消费完,如果消费完,就会取到NONE
            time.sleep(random.randint(1,3))
            print('%s吃了%s'%(name,res))
    
    if __name__ == '__main__':
        p=Queue()
        p1=Process(target=producer,args=('1','葱油拌屎',p,))
        p2 = Process(target=producer, args=('2', '手抓屎', p,))
        p3 = Process(target=producer, args=('3', '飘香拌屎', p,))
        c1=Process(target=customer,args=('姚晓锋',p,))
        c2 = Process(target=customer, args=('阿飞', p,))
        p1.start()
        p2.start()
        p3.start()
    
        c1.start()
        c2.start()
    
        p1.join()
        p2.join()
        p3.join()#说明此时生产者已经生产完了
        p.put(None)#有几个消费者就加上几个NONE
        p.put(None)
        c1.join()
        c2.join()
        print('')
    方式一
    from multiprocessing import  Process,JoinableQueue
    import time,random
    
    def producer(name,food,p):
        for i in range(3):
            res='%s%s'%(food,i)
            time.sleep(random.randint(1,3))
            print('%s生产了%s'%(name,res))
            p.put(res)
    
    def customer(name,p):
        while True:
            res=p.get()
            time.sleep(random.randint(1,3))
            print('%s吃了%s'%(name,res))
    
    if __name__ == '__main__':
        p=JoinableQueue()
        p1=Process(target=producer,args=('1','葱油拌屎',p,))
        p2 = Process(target=producer, args=('2', '手抓屎', p,))
        p3 = Process(target=producer, args=('3', '飘香拌屎', p,))
        c1=Process(target=customer,args=('姚晓锋',p,))
        c2 = Process(target=customer, args=('阿飞', p,))
        c1.daemon=True
        c2.daemon=True
        p1.start()
        p2.start()
        p3.start()
    
        c1.start()
        c2.start()
    
        p1.join()
        p2.join()
        p3.join()
        p.join()#主进程等待队列里为空
        #一旦队列为空,说明消费者取完了队列,消费者没有价值了
        print('')
    方式二

    二、线程理论

    1 什么是线程

    进程其实一个资源单位,而进程内的线程才是cpu上的执行单位
    线程其实指的就是代码的执行过程

    2 为何要用线程

    线程的优点
    1. 同一进程下的多个线程共享该进程内的资源
    2. 创建线程的开销要远远小于进程

    三、开启线程的两种方式

    线程开启的方式与进程一致

    from threading import Thread
    import time
    
    
    def task(name):
        print('%s is running'%name)
        time.sleep(3)
        print('%s is done'%name)
    
    
    if __name__ == '__main__':
        p=Thread(target=task,args=('yxf',))
        p.start()
        print('')
    方式一
    from threading import Thread
    import time
    
    class Mythread(Thread):
        def __init__(self,name):
            super().__init__()
            self.name=name
    
        def run(self):
            print('%s is running'%self.name)
            time.sleep(3)
            print('%s is done'%self.name)
    
    
    if __name__ == '__main__':
        p=Mythread('egon')
        p.start()
        print('')
    方式二

    四、线程特性介绍

    Thread实例对象的方法

      isAlive(): 返回线程是否活动的。

      getName(): 返回线程名。

      setName(): 设置线程名。

    threading模块提供的一些方法

      threading.currentThread(): 返回当前的线程变量。

      threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。 

      threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果

    同一进程下的线程共享资源

    from threading import Thread,current_thread,active_count
    
    
    n=100
    def task():
        global n
        n=0
        print('子进程n=',n,current_thread())
    
    
    
    if __name__ == '__main__':
        p1=Thread(target=task,)
        p1.start()
        print(active_count())
        p1.join()
        print(active_count())
        print('主进程n=',n,current_thread())
    代码验证

    五、守护线程

    守护线程的生命周期取决于被守护线程(主线程)的生命周期,但是主线程要等到非守护线程都结束执行才会执行完毕

    也就是说,只有非守护线程都执行完毕,守护线程才会结束

    from threading import Thread
    import time
    def foo():
        print(123)
        time.sleep(1)
        print("end123")
    
    def bar():
        print(456)
        time.sleep(3)
        print("end456")
    
    if __name__ == '__main__':
        t1=Thread(target=foo)
        t2=Thread(target=bar)
        t1.daemon=True
        t1.start()
        t2.start()
        print("main-------")
    代码验证

    六、线程互斥锁

    与进程一致

    from threading import Thread,Lock
    import time
    
    mutex=Lock()
    n=100
    def task():
        global n
        mutex.acquire()
        temp=n
        time.sleep(0.1)
        n=temp-1
        mutex.release()
    
    if __name__ == '__main__':
        t_l=[]
        for i in range(100):
            t=Thread(target=task)
            t_l.append(t)
            t.start()
    
        for t in t_l:
            t.join()
        print(n)
    代码验证
  • 相关阅读:
    转:javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure 解决方案
    Elementui 导航组件和Vuejs路由结合
    python 在线生成文字云
    TensorFlow创建简单的图片分类系统--机器学习
    kettle maven 配置
    Kettle api 二次开发之 日志的保存
    heatmap for arcgisjsapi
    Spring MVC 使用tomcat中配置的数据源
    点坐标旋转方法
    在servlet中使用Spring注入
  • 原文地址:https://www.cnblogs.com/xvchengqi/p/9599543.html
Copyright © 2011-2022 走看看