Python 多进程、线程、协程的简单使用

多线程 进程 协程

01 threading实现多线程

  1. 导入threading模块
    import threading

  2. 创建对象

    def sing():
        for i in range(5):
            print("------Singing-----")
            time.sleep(1)
            
    ts = threading.Thread(target=sing)
    

    注意 target参数只写函数名,不能加括号,此时只创建了对象,没有创建线程

  3. 控制子线程

    ts.start()  # 启动子线程
    ts.join([time])  # 等待子线程运行完成
    ts.isAlive()  # 返回子线程是否是存活的
    ts.getName()  # 返回子线程名
    ts.setName()  # 设置子线程名
    

    调用start之后才创建了子线程,子线程从start开始执行,目标函数结束后子线程运行结束

  4. 运行多个子线程

    while True:
      length=len(threading.enumerate())
      # print("\n当前运行的进程数:%d\n"%length)
      time.sleep(2)
      if length <= 1:
            print("\n所有子线程已运行完成!!!\n")
            break
    

    len(threading.enumerate())表示当前运行的线程数,包括一个主线程

  5. 通过重载使用多线程

    import threading
    import time
    
    class MyThread(threading.Thread):
        def run(self):
            for i in range(3):
                time.sleep(1)
                print("-----%d-----"%i)
            self.relax()
    
        def relax(self):
            print('-----relax-----\n')
    
    if __name__=='__main__':
        t=MyThread()
        t.start()  
    

    调用start时会自动调用类中的run,因此在类中必须定义run

  6. 互斥锁

    • 创建锁(默认是不加锁的) mutex=threading.Lock()
    • 上锁 mutex.acquire()
    • 解锁 mutex.release()
    • 判断是否上锁 mutex.locker()

02 multiprocessing实现多进程

进程与线程的区别:

  • 进程是资源分配的单位,线程是资源调度的单位
  • 进程需要的资源多 线程需要的资源少
  • 进程如同一条流水线 线程如同流水线上的工人
  1. 导入模块
    import multiprocessing

  2. 创建对象

    import time
    import multiprocessing
    
    def sing():
        for i in range(5):
            print("------Singing-----")
            time.sleep(1)
            
    def dance():
        for i in range(5):
            print("------Dancing-----")
            time.sleep(1)
            
    def main():
       ts=multiprocessing.Process(target=sing)
       td=multiprocessing.Process(target=dance)
    
       ts.start()   
       td.start()  
    
    if __name__=='__main__':
        main()
    
    
    1. 调用start后才创建了子进程,子进程从start开始执行,子线程函数结束后子进程运行结束
    2. 子进程会将主进程的内存复制,复制变量的值。 代码是共享的,不复制 复制的越少越好,能共享就共享
  3. queue实现进程间通信

    import multiprocessing
    
    # 模拟下载数据
    def download_data(q):
        data=[1,2,3,4,5]
        for temp in data:
            q.put(temp)
    
        print('所有数据已经存入!')
    
    # 模拟处理数据
    def data_process(q):
        get_data=list()
        while (q.empty()==False):
            data=q.get()
            get_data.append(data)
        print(get_data)
    
    def main():
        #创建一个队列
        q=multiprocessing.Queue()  
        
        p1=multiprocessing.Process(target=download_data,args=(q,))
        p2=multiprocessing.Process(target=data_process,args=(q,))
        p1.start()
        p2.start()
    
    if __name__=='__main__':
        main()
    
      1. queue在内存中开辟空间,储存用于通信的数据
    
    1. queue只能用于同一个电脑的同一个程序

    2. 不指定队列大小时,根据内存自动确定大小

    3. 创建进程传递参数时,要注意传递的是一个元组,要加逗号

  4. 进程池
    在任务数不确定时,往往使用进程池

    import multiprocessing
    import os,time,random
    
    def job(msg):
        t_start=time.time()
        print('%s开始执行,进程号为:%d'%(msg,os.getpid()))
        time.sleep(random.random()*3)
        t_stop=time.time()
        t_cost=t_stop - t_start
        print('%s执行执行完毕,耗时%0.2fs' % (msg, t_cost))
    
    def main():
        po=multiprocessing.Pool(3)  # 设置进程池容量为3
        for i in range(10):
            po.apply_async(job,(i,))  # 两个参数为要执行的函数名和传递参数元组
    
        print('----start----')
        po.close()  # 关闭进程池
        po.join()  # 等待池中所有进程执行结束 必须在close之后
        print('----end----')
    
    if __name__=='__main__':
        main()
    
    1. 创建容纳三个进程的进程池去执行九个任务
    2. 进程池使用queue通信时,要使用manager下的queue
      如q=multiprocessing.Manager().Queue()

03 gevent实现协程

  1. gevent再遇到延时函数时会自动切换协程,但要注意需要使用gevent中的延时函数,如将time.sleep()换成gevent.sleep()
    如果想要使用原来的延时函数,可以添加语句:

     gevent.monkey.patch_all()
    
  2. 启动多个协程的方法

    gevent.joinall(
        [
            gevent.spawn(f1,5),
            gevent.spawn(f2,5),
            gevent.spawn(f3,5)  # 设置目标函数并传递参数
        ]
    )
    

    协程传递参数使用的不是元组

  3. 代码示例

    from gevent import monkey
    
    gevent.monkey.patch_all()
    
    def f1(n):
        for i in range(n):
            print('f1:',i)
            time.sleep(1)
    
    def f2(n):
        for i in range(n):
            print('f2:',i)
            time.sleep(1)
    
    def f3(n):
        for i in range(n):
            print('f3:',i)
            time.sleep(1)
    
    
    gevent.joinall(
        [
            gevent.spawn(f1,5),
            gevent.spawn(f2,5),
            gevent.spawn(f3,5)
        ]
    )
    

你可能感兴趣的:(Python 多进程、线程、协程的简单使用)