zoukankan      html  css  js  c++  java
  • python进程|线程|协程

    进程(Process)

      1)进程就是正在运行的程序,它是操作系统中,资源分配的最小单位

      (1)资源分配:分配的是cpu和内存等物理资源

      (2)进程号是进程的唯一标识

      2)同一个程序执行两次之后是两个进程

      3)进程和进程之间的关系: 数据彼此隔离,通过socket通信

    获取进程id

    import os
    res = os.getpid() # 获取当前进行id (当前子进程)
    print(res)
    res = os.getppid() # 获取父进程id
    print(res)
    
    # result 
    """
    13724
    13800
    """

    进程的基本用法

    from multiprocessing import Process
    import time
    import os
    def func():
        print("S2>>>当前子进程id:%s,它的父进程id:%s" %(os.getpid(),os.getppid()))
    
    if __name__ == "__main__":
        print("S1>>>子进程id:%s,父进程id:%s"%(os.getpid(),os.getppid()))
        p = Process(target=func) # 创建子进程 target = 函数 单独用一个进程去执行谁,去完成哪个任务
        p.start() # 调用子进程
    
    # result
    """
    S1>>>子进程id:7576,父进程id:13800
    S2>>>当前子进程id:7100,它的父进程id:7576
    """

    带有参数的函数

      异步程序:不等没一行代码执行完毕,就往下执行其它代码

    from multiprocessing import Process
    import time
    import os
    def func():
        for i in range(1,5):
            print("S2>>>当前子进程id:%s,它的父进程id:%s"%(os.getpid(),os.getppid()))
    
    if __name__ == "__main__":
        print("S1>>>子进程id:%s,父进程id:%s"%(os.getpid(),os.getppid()))
        p = Process(target=func)
        p.start()
    
        n = 5
        for i in range(1,n+1):
            print("*" * i )
            
    # result 
    """
    S1>>>子进程id:7928,父进程id:13800
    *
    **
    ***
    ****
    *****
    S2>>>当前子进程id:8112,它的父进程id:7928
    S2>>>当前子进程id:8112,它的父进程id:7928
    S2>>>当前子进程id:8112,它的父进程id:7928
    S2>>>当前子进程id:8112,它的父进程id:7928
    """

    进程之间数据,彼此隔离

    from multiprocessing import Process
    import time
    import os
    count = 99
    def func():
        global count
        count += 1
        print("当前子进程id:%s"%(os.getpid()),count)
    
    if __name__ == "__main__":
        p = Process(target=func)
        p.start()
        time.sleep(1) # 让子进程跑完,看是否通过子进程修改
        print("主进程",count)
    
    # result 
    """
    当前子进程id:1956 100
    主进程 99
    """

    多进程之间的并发

      多程序并发时,因为cpu的调度策略,任务的执行是互相抢占cpu资源的过程

    from multiprocessing import Process
    import time
    import os
    def func(args):
        print("S2>>>当前子进程id:%s,它的父进程id:%s"%(os.getpid(),os.getppid()))
        print("end>>>",args)
    
    if __name__ == "__main__":
        for i in range(10):
            Process(target=func,args=(i,)).start()
        print("主进程执行结束...")
        
    # result 
    """
    主进程执行结束...
    S2>>>当前子进程id:10376,它的父进程id:9932
    end>>> 2
    S2>>>当前子进程id:13476,它的父进程id:9932
    end>>> 1
    S2>>>当前子进程id:11812,它的父进程id:9932
    end>>> 3
    S2>>>当前子进程id:13936,它的父进程id:9932
    end>>> 4
    S2>>>当前子进程id:2384,它的父进程id:9932
    end>>> 7
    S2>>>当前子进程id:7024,它的父进程id:9932
    end>>> 5
    S2>>>当前子进程id:14284,它的父进程id:9932
    end>>> 8
    S2>>>当前子进程id:4816,它的父进程id:9932
    end>>> 9
    S2>>>当前子进程id:120,它的父进程id:9932
    end>>> 6
    S2>>>当前子进程id:8604,它的父进程id:9932
    end>>> 0
    """

    主进程和子进程之间的关系

    (1)主进程执行完所有代码,等待子进程全部结束,再终止程序

    (2)不等待,子进程变成僵尸用户,在后台不停运行,耗费资源

    from multiprocessing import Process
    import time
    import os
    def func(args):
        print("S2>>>当前子进程id:%s,它的父进程id:%s"%(os.getpid(),os.getppid()))
        time.sleep(0.1)
        print("end>>>",args)
    
    if __name__ == "__main__":
        for i in range(10):
            Process(target=func,args=(i,)).start()
        print("主进程执行结束...")
        
    # result 
    """
    主进程执行结束...
    S2>>>当前子进程id:10092,它的父进程id:6304
    S2>>>当前子进程id:11220,它的父进程id:6304
    S2>>>当前子进程id:12992,它的父进程id:6304
    S2>>>当前子进程id:8384,它的父进程id:6304
    S2>>>当前子进程id:3824,它的父进程id:6304
    S2>>>当前子进程id:12880,它的父进程id:6304
    S2>>>当前子进程id:6352,它的父进程id:6304
    end>>> 0
    end>>> 2
    S2>>>当前子进程id:7160,它的父进程id:6304
    end>>> 9
    end>>> 7
    S2>>>当前子进程id:6676,它的父进程id:6304
    end>>> 5
    end>>> 8
    end>>> 3
    S2>>>当前子进程id:7488,它的父进程id:6304
    end>>> 1
    end>>> 6
    end>>> 4
    """

    join

      等待子进程执行完毕之后,主进程再向下执行

    基本用法

    from multiprocessing import Process
    import time
    import os
    def func():
        print("发送第一封邮件")
    
    if __name__ == "__main__":
        p = Process(target=func)
        p.start()
        time.sleep(1)
        p.join() # 针对于p进程对象来说,必须等待p这个进程任务执行完毕之后,主进程的代码在向下执行
        print("发送第二封邮件")
        
    # result 
    """
    发送第一封邮件
    发送第二封邮件
    """

    多个子进程

      多个子进程通过join加阻塞,可以实现同步控制

    from multiprocessing import Process
    import time
    import os
    def func(index):
        print("第%s封邮件发送..."%(index))
    
    if __name__ == "__main__":
        lst = [] # 初始化一个列表
        for i in range(5):
            p = Process(target=func,args=(i,))
            p.start()
            lst.append(p)
            p.join()
    
        # 循环列表中每一个进程,都加上join,保证每个子进程执行完毕,保证同步性
        for i in lst:
            i.join()
        print("发送最后一封邮件...")
        
    # result 
    """
    第0封邮件发送...
    第1封邮件发送...
    第2封邮件发送...
    第3封邮件发送...
    第4封邮件发送...
    发送最后一封邮件...
    """

    自定义类方式创建进程

    基本用法

    from multiprocessing import Process
    import time
    import os
    class MyProcess(Process): # 必须继承父类Process
        def run(self): # 必须写成run方法
            print(">>>子进程id:%s,父进程id:%s"%(os.getpid(),os.getppid()))
    
    if __name__ == "__main__":
        p = MyProcess()
        p.start()
        print(">>>主进程id:%s"%(os.getpid()))
        
    # result 
    """
    >>>主进程id:9988
    >>>子进程id:14248,父进程id:9988
    """

    带参数子进程函数

    from multiprocessing import Process
    import time
    import os
    class MyProcee(Process):
        def __init__(self,arg):
            super().__init__() # 必须调用一下父类的构造方法
            self.arg = arg
        def run(self):
            print(">>>子进程id:%s,父进程id:%s"%(os.getpid(),os.getppid()))
            print(self.arg)
    
    if __name__ == "__main__":
        lst = []
        for i in range(10):
            p = MyProcee("参数:%s"%(i))
            p.start()
            lst.append(p)
    
        for i in lst:
            i.join()
        print("最后打印子进程id",os.getppid())
        
    # result 
    """
    >>>子进程id:7488,父进程id:8596
    参数:6
    >>>子进程id:11300,父进程id:8596
    参数:8
    >>>子进程id:12048,父进程id:8596
    参数:4
    >>>子进程id:7868,父进程id:8596
    参数:0
    >>>子进程id:4792,父进程id:8596
    参数:5
    >>>子进程id:10764,父进程id:8596
    参数:2
    >>>子进程id:10852,父进程id:8596
    参数:1
    >>>子进程id:9348,父进程id:8596
    参数:3
    >>>子进程id:9860,父进程id:8596
    参数:7
    >>>子进程id:8956,父进程id:8596
    参数:9
    最后打印子进程id 13800
    """

    并行和并发

    (1)并行:一个cpu同一时间不停执行多个程序

    (2)并发:多个cpu同一时间不停执行多个程序

    cpu的进程调度方法

    (1)先来先服务fcfs(first come first server):先来的先执行

    (2)短作业优先算法:分配的cpu多,先把短的算完

    (3)时间片轮转算法:每一个任务就执行一个时间片的时间.然后就执行其他的

    (4)多级反馈队列算法

        越是时间长的,cpu分配的资源越短,优先级靠后,越是时间短的,cpu分配的资源越多

    进程三状态图

    (1)就绪(Ready)状态-->只剩下CPU需要执行外,其他所有资源都已分配完毕 称为就绪状态。

    (2)执行(Running)状态 --> cpu开始执行该进程时称为执行状态

    (3)阻塞(Blocked)状态 --> 由于等待某个事件发生而无法执行时,便是阻塞状态,cpu执行其他进程.例如,等待I/O完成input、申请缓冲区不能满足等

    同步|异步/阻塞|非阻塞

    场景在多任务中

      同步:必须等我这件事干完了,你在干,只有一条主线,就是同步

      异步:没等我这件事情干完,你就在干了,有两条主线,就是异步

      阻塞:比如代码有了input,就是阻塞,必须要输入一个字符串,否则代码不往下执行

      非阻塞:没有任何等待,正常代码往下执行

      同步阻塞:效率低,cpu利用不充分

      异步阻塞:比如socketserver,可以同时连接多个,但是彼此都有recv

      同步非阻塞:没有类似input的代码,从上到下执行.默认的正常情况代码

      异步非阻塞:效率是最高的,cpu过度充分,过度发热

    守护进程

      可以给子进程贴上守护进程的名字,该进程会随着主进程代码执行完毕而结束(为主进程守护)

      (1)守护进程会在主进程代码执行结束后就终止

      (2)守护进程内无法再开启子进程,否则抛出异常(了解)

     基本用法

    from multiprocessing import Process
    import time
    import os
    def func():
        print("子进程start...")
        time.sleep(0.1)
        print("子进程end...")
    
    if __name__ == "__main__":
        p = Process(target=func)
        p.daemon = True # 在start开始前设置该进程为守护进程
        p.start()
        print("主进程执行结束...")
        
    # result 
    """
    主进程执行结束...
    """

     多个子进程

      (1)当主进程里面的代码全部执行完毕,守护进程自动终止

      (2)func1是守护进程,func2是非守护进程

    from multiprocessing import Process
    import time
    import os
    def func1():
        count = 1
        while True:
            print("*" * count)
            time.sleep(0.5)
            count += 1
    
    def func2():
        print("func2 start...")
        time.sleep(2)
        print("func2 end...")
    
    if __name__ == "__main__":
        p1 = Process(target=func1)
        p1.daemon = True
        p2 = Process(target=func2)
        p1.start()
        p2.start()
    
        time.sleep(1)
        print("主进程代码执行完毕...")
    
    # result
    """
    func2 start...
    *
    **
    主进程代码执行完毕...
    func2 end...
    """

     守护进程应用--报活

    from multiprocessing import Process
    import time
    import os
    def alive():
        while True:
            print("一号服务主机ok...")
            time.sleep(1) # 相隔1秒报活
    
    def func():
        print("一号服务主机负责统计日志信息")
        time.sleep(3)
    
    if __name__ == "__main__":
        p1 = Process(target=alive)
        p1.daemon = True
        p1.start()
        p2 = Process(target=func)
        p2.start()
        p2.join() # join添加阻塞,join执行结束,代表服务统计功能失败
        print(" ... ")
    
    # result
    """
    一号服务主机ok...
    一号服务主机负责统计日志信息
    一号服务主机ok...
    一号服务主机ok...
    一号服务主机ok...
     ... 
    """

     锁(LOCK)

    (1)lock.acquire() 上锁

    (2)lock.release() 解锁

    (3)同一时间允许一个进程上一把锁,就是lock。加锁可以保证多个进程修改同一块数据,同一时间只能有一个任务进行修改,即串行修改,速度慢,保证安全。

    (4)同一时间允许多个进程上多把锁,就是信号量[Semaphore]

        信号量是锁的变形:实现是 计数器 + 锁,同时允许多个进程上锁

    (5)互斥锁Lock:就是进程的互相排斥,谁先抢到资源,谁就上锁修改资源内容,保证数据的同步性

        多个锁一起上,不开锁,会造成死锁,上锁和解锁是一对

    基本语法

    import json,time
    lock = Lock() # 创建一把锁
    lock.acquire() # 上锁
    print(123)
    lock.release() # 解锁

    死锁

      程序添加了阻塞,程序不能往下执行。下面代码程序阻塞,也不会打印111

    lock = Lock() # 创建一把锁
    lock.acquire() # 上锁
    lock.acquire()
    print(111)
    lock.release() # 解锁

      抢票示例

    from multiprocessing import Lock,Process
    import time
    count = 1
    def get_ticket(person):
        global  count
        time.sleep(0.1)
        if count > 0:
            print("%s抢到票了..."%(person))
            count -= 1
        else:
            print("%s没有抢到票..."%(person))
    
    # 定义一个函数来进行统一调用
    def ticket(person,lock):
        print("%s 查询余票:%s"%(person,count)) # 查询余票
        lock.acquire()
        get_ticket(person)
        lock.acquire()
    
    if __name__ == "__main__":
        lock = Lock()
        for i in range(10):
            p = Process(target=ticket,args=("person%s"%(i),lock))
            p.start()
    
    # result
    """
    person6 查询余票:1
    person0 查询余票:1
    person1 查询余票:1
    person6抢到票了...
    person4 查询余票:1
    person9 查询余票:1
    person3 查询余票:1
    person8 查询余票:1
    person2 查询余票:1
    person7 查询余票:1
    person5 查询余票:1
    """

    信号量

      本质上就是锁,只不过可以控制锁的数量

    from multiprocessing import Process, Semaphore
    import os, time
    
    def ktv(person, sem):
        sem.acquire()
        print("%s进入ktv开始唱歌" % (person))
        print(os.getpid())
        time.sleep(3)
        print("%s走出ktv离开歌房" % (person))
        sem.release()
    
    if __name__ == "__main__":
        sem = Semaphore(1)
        for i in range(5):
            p = Process(target=ktv, args=("person%s" % (i), sem))
            p.start()
    
    # result 
    """
    person3进入ktv开始唱歌
    15956
    person3走出ktv离开歌房
    person2进入ktv开始唱歌
    14632
    person2走出ktv离开歌房
    person4进入ktv开始唱歌
    9248
    person4走出ktv离开歌房
    person1进入ktv开始唱歌
    8816
    person1走出ktv离开歌房
    person0进入ktv开始唱歌
    12992
    person0走出ktv离开歌房
    """

    事件(Event)

    (1)阻塞事件

        e = Event() 生成事件对象e

        e.wait() 动态给程序加阻塞,程序当中是否加阻塞完全取决于该对象中的is_set() [默认返回值是False],True不加阻塞

    (2)控制这个属性的值

        set() 方法:将这个属性的值改成True

        clear() 方法:将这个属性的值改成False

        is_set() 方法:判断当前的属性是否为True  (默认上来是False)

    基本语法

    from multiprocessing import Process,Event
    import time,random
    e = Event()
    print(e.is_set())
    e.wait(1) # 最多阻塞时间为1秒
    print(111)
    
    # result 
    """
    False
    111
    """
    from multiprocessing import Process,Event
    import time,random
    e = Event()
    e.set() # 将内部属性改成True
    e.wait()
    print(111)
    e.clear() # 将内部属性改成False
    e.wait()
    print(222)
    
    # result 
    """
    111
    """

    模拟交通灯

      (1)两个信号灯会交替变换

    from multiprocessing import Process,Event
    import time,random
    def traffic_light(e):
        print("红灯亮")
        while True:
            if e.is_set():
                time.sleep(1) # 当前绿灯,等待1秒
                print("红灯亮") # 等完1秒后,变成红灯
                e.clear()
            else:
                time.sleep(1) # 当前是红灯
                print("绿灯亮")
                e.set()
    e = Event()
    traffic_light(e)

      (2)模拟车遇到红灯停,绿灯行的操作

    from multiprocessing import Process,Event
    import time,random
    def traffic_light(e):
        print("红灯亮")
        while True:
            if e.is_set():
                time.sleep(1) # 当前绿灯,等待1秒
                print("红灯亮") # 等完1秒后,变成红灯
                e.clear()
            else:
                time.sleep(1) # 当前是红灯
                print("绿灯亮")
                e.set()
    
    def car(e,i):
        if not e.is_set():
            print("car%s在等待..."%(i))
            e.wait()
        print("car%s通行..."%(i))
    
    if __name__ == "__main__":
        e = Event()
        lst = []
        p1 = Process(target=traffic_light,args=(e,))
        p1.daemon = True # 设置守护进程,小车跑完,交通灯终止
        p1.start()
        # 模拟通行
        for i in range(5):
            time.sleep(random.uniform(0,2)) # 随机停0-2秒
            p2 = Process(target=car,args=(e,i))
            p2.start()
            lst.append(p2) # 将进程添加到列表中
            for i in lst:
                i.join() # 等所有车跑完,终止交通灯;加一个等待
            print("程序结束...")
    
    # result
    """
    红灯亮
    绿灯亮
    car0通行...
    程序结束...
    红灯亮
    car1在等待...
    绿灯亮
    car1通行...
    程序结束...
    car2通行...
    程序结束...
    红灯亮
    car3在等待...
    绿灯亮
    car3通行...
    程序结束...
    car4通行...
    程序结束...
    """

    进程间通信IPC

    (1)IPC Inter-Process Communication

    (2)进程之间通信的两种机制:管道Pipe 队列 Queue

    (3)put() 存放

    (4)get() 获取

    (5)get_nowait() 拿不到报异常

    (6)put_nowait() 非阻塞版本的put

    (7)q.empty() 检测是否为空

    (8)full() 检测是否已经存满

    基本语法

      (1)先进先出,后进后出

      (2)让进程之间形成数据之间的共享

    from multiprocessing import Process,Queue
    q = Queue()
    q.put(1) # 把数据放到q队列中
    res = q.get() # 把数据从队列中取出
    print(res)
    res = q.get() # 没有数据后会形成阻塞
    res = q.get_nowait() # 没有数据,直接报错

    queue指定队列长度

    from multiprocessing import Queue
    q = Queue(3)
    q.put(1)
    q.put(2)
    q.put(3)
    # q.put(4) # 存放值满了,阻塞
    q.put_nowait(5) # 往队列中存值,满直接报错

     进程通信,依赖Queue

    from multiprocessing import Queue,Process
    # 子进程
    def func(q):
        res = q.get() # 子进程获取数据
        print(res)
        q.put(1) # 子进程添加数据
    
    if  __name__ == "__main__":
        q = Queue()
        p = Process(target=func,args=(q,))
        p.start()
        q.put(2) # 主进程添加数据
        p.join()
        res = q.get() # 主进程添加数据
        print(res)
        print("程序结束...")
    
    # result
    """
    2
    1
    程序结束...
    """

     生产者与消费者模型

    如:1号进程负责爬取网页中内容,2号进程负责匹配提取网页中关键字

      1号进程可以看成一个生产者,2号进程可以看成一个消费者

    from multiprocessing import Process,Queue
    import os,random,time
    # 消费者模型(负责取值)
    def consumer(q,name):
        while True:
            food = q.get() # 拿出数据
            if food is None:
                break
            time.sleep(random.uniform(0.1,1))
            print("%s 吃了一个 %s"%(name,food))
    
    # 生产者模型(负责存值)
    def producer(q,name,food):
        for i in range(3):
            time.sleep(random.uniform(0.1,1))
            print("%s 生产了 %s,%s"%(name,food,i))
            q.put(food + str(i))
    
    if __name__ == "__main__":
        q = Queue()
        c1 = Process(target=consumer,args=(q,"A"))
        c1.start()
        p1 = Process(target=producer,args=(q,"B","egg"))
        p1.start()
        p1.join()
        q.put(None)
    
    # result 
    """
    B 生产了 egg,0
    A 吃了一个 egg0
    B 生产了 egg,1
    A 吃了一个 egg1
    B 生产了 egg,2
    A 吃了一个 egg2
    """

    进程池

    (1)开启过多的进程并不一定提高效率

         cpu负载任务过多,平均单个任务执行效率低,较低执行速度

    (2)apply 开启进程,同步阻塞,每次都要等待当前任务完成之后,开启下一个进程

    (3)apply_async 开启进程,异步非阻塞(主进程和子进程异步)

    线程

    (1)进程是资源分配的最小单位,线程是计算机中调度的最小单位

    (2)线程的缘起

        资源分配需要分配内存空间,分配cpu,分配的内存空间存放着临时要处理的数据,如要执行的代码,数据。

    (3)线程的特点

        轻量级,能干更多的活,一个进程中所有线程资源共享,一个进程至少一个线程工作

     一个进程可以有多个线程,共享一份资源

    from threading import Thread
    from multiprocessing import Process
    import os,time,random
    def func(num):
        time.sleep(random.uniform(0.1,1))
        print("子线程",num,os.getpid())
    
    if __name__ == "__main__":
        for i in range(5):
            t = Thread(target=func,args=(i,))
            t.start()
    
    # result 
    """
    子线程 1 6348
    子线程 3 6348
    子线程 0 6348
    子线程 4 6348
    子线程 2 6348
    """

    并发多进程线程对比

    from threading import Thread
    from multiprocessing import Process
    import os,time,random
    # 计算多线程时间
    def func(i):
        # print("子线程",i,os.getpid())
        pass
    
    if __name__ == "__main__":
        lst = []
        start_time = time.time()
        for i in range(100):
            t = Thread(target=func,args=(i,))
            t.start()
            lst.append(t)
    
        for i in lst:
            i.join()
    
        end_time = time.time()
        print("time:",end_time-start_time)
    
    # result
    """
    time: 0.02393651008605957
    """
    from threading import Thread
    from multiprocessing import Process
    import os,time,random
    def func(i):
        # print("子线程",i,os.getpid())
        pass
    
    if __name__ == "__main__":
        lst = []
        start_time = time.time()
        for i in range(100):
            p = Process(target=func,args=(i,))
            p.start()
            lst.append(p)
    
        for i in lst:
            i.join()
    
        end_time = time.time()
        print("time:",end_time-start_time)
    
    # result
    """
    time: 13.565200328826904
    """

    多线程共享同一份进程资源

    from threading import Thread
    from multiprocessing import Process
    import os,time,random
    num = 100
    lst = []
    def func(i):
        global num
        num -= 1
    
    for i in range(100):
        t = Thread(target=func,args=(i,))
        t.start()
        lst.append(t)
    
    for i in lst:
        i.join()
    
    print(num)
    
    # result
    """
    0
    """

    线程相关函数

    (1)线程.is_alive() 检测线程是否仍然存在

    (2)线程.setName() 设置线程名字

    (3)线程。getName() 获取线程名字

    (4)currentThread().ident 查看线程id

    (5)enumerate() 返回目前正在运行的线程列表

    (6)activeCount() 返回目前正在运行的线程数量

    查看线程id

    from threading import currentThread,Thread
    import os
    def func():
        print("子线程",currentThread().ident)
    t = Thread(target=func)
    t.start()
    print("主线程",currentThread().ident,os.getpid())
    
    # result 
    """
    子线程 9952
    主线程 912 13268
    """

    enumerate()

    from threading import currentThread,Thread,enumerate
    import os,time
    def func():
        print("子线程",currentThread().ident)
        time.sleep(0.5)
    
    for i in range(5):
        t = Thread(target=func)
        t.start()
    print(enumerate())
    print(len(enumerate()))
    
    # result 
    """
    子线程 3668
    子线程 5856
    子线程 13288
    子线程 6304
    子线程 5496
    [<_MainThread(MainThread, started 8644)>, <Thread(Thread-1, started 3668)>, <Thread(Thread-2, started 5856)>, <Thread(Thread-3, started 13288)>, <Thread(Thread-4, started 6304)>, <Thread(Thread-5, started 5496)>]
    6
    """

    activeCount()

    from threading import currentThread,Thread,enumerate,activeCount
    import os,time
    def func():
        print("子线程",currentThread().ident)
        time.sleep(1)
    
    for i in range(5):
        Thread(target=func).start()
    
    print(activeCount())
    
    # result 
    """
    子线程 5168
    子线程 3428
    子线程 13808
    子线程 11732
    子线程 2756
    6
    """

    守护线程

      等待所有线程执行结束后自动结束,守护所有线程

    from threading import currentThread,Thread,enumerate,activeCount
    import os,time
    def func1():
        while True:
            time.sleep(1)
            print("线程1")
    
    def func2():
        print("线程2-start")
        time.sleep(2)
        print("线程2-end")
    
    t1 = Thread(target=func1)
    t1.setDaemon(True)
    t1.start()
    t2 = Thread(target=func2)
    t2.start()
    print("主线程执行结束...")
    
    # result 
    """
    线程2-start
    主线程执行结束...
    线程1
    线程2-end
    """

    线程的数据安全 依赖Lock

    from threading import currentThread,Thread,enumerate,activeCount,Lock
    import os,time
    n = 0
    def func1(lock):
        global n
        for i in range(1000):
            lock.acquire() # 上锁
            n -= 1
            lock.release() # 解锁
    
    def func2(lock):
        global n
        for i in range(1000):
            with lock:
                n += 1
    
    if __name__ == "__main__":
        lock = Lock()
        lst = []
        for i in range(5):
            t1 = Thread(target=func1,args=(lock,))
            t2 = Thread(target=func2,args=(lock,))
            t1.start()
            t2.start()
            lst.append(t1)
            lst.append(t2)
    
        for i in lst:
            i.join()
        print("主线程结束")
        print(n)
    
    # result 
    """
    0
    """

    信号量

    from threading import currentThread,Thread,enumerate,activeCount,Lock,Semaphore
    import os,time,random
    def func(i,sem):
        time.sleep(random.uniform(0.1,1))
        with sem:
            print(i)
            time.sleep(2)
    
    if __name__ == "__main__":
        sem = Semaphore(5)
        for i in range(5):
            Thread(target=func,args=(i,sem)).start()
    
    # result 
    """
    2
    1
    0
    4
    3
    """

    死锁,递归锁,互斥锁

    线程队列

    协程(gevent)

    (1)协程也叫纤程,协程是线程的一种实现

        一条线程可以在多任务之间来回切换,对于cpu,操作系统协程不存在

    (2)协程的实现

        协程记住任务执行到那个位置,并且实现安全的切换

        一个任务一旦阻塞,立刻切换到另一个任务继续执行,保证线程总是忙碌

    (3)一个线程可以由多个协程实现,协程之间不会产生数据安全问题

    (4)协程模块

        greenlet gevent的底层,协程,切换的模块

        gevent 直接用,gevent能提供更全面的功能

    def gen():
        for i in range(5):
            yield i
    
    mygen = gen()
    for i in mygen:
        print(i)
    
    # result 
    """
    0
    1
    2
    3
    4
    """

    协程改写生产者消费者模型

    def producer():
        for i in range(5):
            yield i
    
    def consumer():
        g = producer()
        for i in g:
            print(i)
    
    consumer()
    
    # result 
    """
    0
    1
    2
    3
    4
    """

    协程的具体实现

    import time
    from greenlet import greenlet
    
    
    def eat():
        print("eat one")
        g2.switch()
        time.sleep(3)
        print("eat two")
    
    
    def play():
        print("play one")
        time.sleep(1)
        print("playtwo")
        g1.switch()
    
    
    g1 = greenlet(eat)
    g2 = greenlet(play)
    g1.switch()
    
    # result 
    """
    eat one
    play one
    playtwo
    eat two
    """

    gevent不能识别阻塞

    from gevent import monkey
    # mokey.patch_all 可以把下面引入的所有模块中的阻塞,重新识别出来
    monkey.patch_all()
    import time
    import gevent
    
    def eat():
        print("eat one")
        time.sleep(1)
        print("eat two")
        
    def play():
        print("play one")
        time.sleep(1)
        print("playtwo")
    
    g1 = gevent.spawn(eat)
    g2 = gevent.spawn(play)
    
    g1.join()
    g2.join()
    print("主线程执行结束")
    
    # result 
    """
    eat one
    play one
    eat two
    playtwo
    主线程执行结束
    """
  • 相关阅读:
    MD5工具类
    新搭建mysql容易出现问题
    docker自动化部署
    k8s入门案例
    docker单一部署jenkins
    Sentinel 学习-简介
    mysql innerjoin,leftjoin,group by,having
    批量更新 分割list 多线程处理
    redis 3.0+ cluser 集群搭建
    ELK 和 Logstach
  • 原文地址:https://www.cnblogs.com/wangzihong/p/11405047.html
Copyright © 2011-2022 走看看