• 多进程和多线程


    <!doctype html>

    python-多进程和多线程

    python-多进程和多线程

    1.多任务

    多任务处理

    定义:使得计算机可以同时处理多个任务

    串行:一个任务运行完之后,再执行处理另一个任务的状态

    并发:表示多个任务同时执行。但是有可能在内核是串行执行的。任务被分成了多个时间片,不断切换上下文执行。

    并行:多个任务同时运行的状态

    2.多进程

    程序:是一个指令集合

    进程:正在执行的程序;或者说当你运行程序,你就启动一个进程

    -编写的代码,没有运行时,被称为程序,正在运行的代码,叫进程

    并发:计算机中,操作系统轮流让各个任务交替执行,由于cpu的执行速度太快了,我们感觉就像是所有任务都在同时进行

    多进程中,每个进程中所有数据(包括全局变量)都各自拥有一份,互不影响

    from time import sleep
    def sing():
        for i in range(3):
            print('正在唱歌')
            dance()
            sleep(1)
    def dance():
        print('正在跳舞')
    这就是一个简单的多进程
    

    如何创建一个多进程

    • 程序开始运行时,首先会创建一个主进程

    • 在主进程(父进程)下,我们可以创建新的进程(子进程),子进程依赖于主进程,如果主进程结束,程序会退出

    • python提供了非常好用的进程包multiprocessing,借助这个包,可以轻松完成从单进程到并发执行的转换

    • multiprocessing模块提供了一个Process类创建一个进程对象

      from multiprocessing import Process
      def run(name):
          print("子进程进行中,name = %s"%(name))
      if __name__ = "__main__":
          print("父进程启动")
          p = Process(target = run,args = ('test',))
          #target表示调用对象,args表示调用对象的位置参数元组
          #(注意:元组中只有一个参数时,后面要加逗号)
          print("子进程将要执行")
          p.start()
          print(p.name,p.pid)
          #p.name是子进程的名称在 p = Process(target = run,args = ('test',),name = '子进程名称')
          #p.pid 查看子进程的编号
      
      if __name__ == "__main__":说明
          一个python的文件有两种使用方法,第一是作为程序执行,第二是import 到其他的Python程序中被调用(模块重用)执行
      
      因此if __name__ == &quot;__main__&quot;:的作用就是控制这两种情况执行代码的过程,——__name__是内置变量,用于表示当前模块的名字
          
          在if__name__ == &#39;__main__&#39;:下的代码只有在文件作为程序直接才会被执行,而import到其他程序中是不会被执行的
              
          在windows上,子程序会自动启动他的这个文件,而在import的时候是会执行这些语句的。注意:import时倒入整个当前。.py文件
          为了避免import无限递归创建子程序,在创建子程序之前加入if __name__ ==&quot;__main__&quot;:,所以必须把创建子进程的部分用那个if判断保护起来
          import的时候__name__不是__main__,就不会运行了
      

      参数介绍

      -target表示调用对象,即子程序要执行的任务

      -args表示调用对象的位置参数元组,args = (1,)

      -name表示子进程的名称

      Process类常用方法

      -p.start():启动进程,并调用该子进程中的p.run()

      -p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类一定要实现该方法

      -p.terminate() (了解) 强制终止进程p,不会进行任何清理操作

      -p.is_alive():如果p任然运行,返回True.用来判断进程是否在运行

      -p.join([timeout]):主进程等待p终止,timeout是可选的超时时间

      p.join(timeout = 3)
      #三秒后终止程序
      

      Process类常用属性:

      name:当前进程实例别名,默认为Process-N,N为从1开始递增的整数;

      pid:为当前实例的PID值

    危险并发:

    from multiprocessing import Process
    num = 1
    def run1():
        global num
        num += 5
        print("子程序1运行中,num = %d"%(num))
    

    def run2():
    global num
    num += 5
    print('子程序2运行中,num = %d'%(num))

    if name == "main":
    print("父进程启动")
    p1 = Process(target = run1)
    p2 = Process(target= run2)
    print("子程序将要执行")
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    print("子程序结束")

    运行结果为:子程序1运行中 6
    子程序2运行中 11

    通过自定义类的进程

    通过类方式,可以自定义一个类,继承Process类,每次实例化这个类的时候,就等同于实例化一个进程对象

    import multiprocessing
    import time
    class Process_(multiprocessing.Process):
        def run(self):
            n = 5
            while n > 0:
                print(n)
                time.sleep(1)
                n -= 1
    if __name__ == "__main__":
        p = Process_()
        p.start()
        p.join()  
    

    线程池和进程池

    from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
    from multiprocessing import cpu_count
    

    def task(n):

    print(n)
    

    if name == 'main':
    # 进程池
    p = ProcessPoolExecutor(cpu_count())
    for i in range(100):
    p.submit(task, i)
    p.shutdown()

    # 线程池
    t = ThreadPoolExecutor(cpu_count())
    for i in range(100):
        t.submit(task, i)
    t.shutdown()
    

    进程池

    实例

    from multiprocessing import Pool
    import random
    import time
    def work(num):
        print(random.random*num)
        time.sleep(3)
    if __name__ == "__main__":
        po = Pool(3)   #定义一个进程池,最大进程数为3,默认大小为CPU核数
        for i in range(10):
            po.apply_async(work,(i,))
        po.close()       #进程池关闭后不再接受新的请求
        po.join()        #等待po中所有子进程结束,必须放在close后面
    

    在多进程中:主进程一般用来等待,真正的任务都在子进程中执行

    multiprocessing.Pool常用函数解析:

    -apply_async(func[,args[,kwds]]):使用非阻塞方式调用func(并行执行,阻塞方式必须等待上一个进程退出才能执行下一个进程),args为传递给func的参数列表,kwds为传递给func的关键字参数列表;

    -apply(func[,args[,kwds]])(了解即可) 使用阻塞方式调用func

    -close(): 关闭Pool,使其不在接收新的任务;

    -join(): 主进程阻塞,等待子进程的退出,必须在close或terminate之后使用

    进程池的应用:进程池的出现是为了有效的控制进程执行的数量,已达到系统稳定的效果

    单进程

    实例

    from multiprocessing import Process
    def run(name):
        print("子进程进行中,name = %s"%(name))
    if __name__ = "__main__":
        print("父进程启动")
        p = Process(target = run,args = ('test',))
        #target表示调用对象,args表示调用对象的位置参数元组
        #(注意:远足中只有一个参数时,后面要加逗号)
        print("子进程将要执行")
        p.start()
        print(p.name,p.pid)
        #p.name是子进程的名称在 p = Process(target = run,args = ('test',),name = '子进程名称')
        #p.pid 查看子进程的编号
    
  • 相关阅读:
    ETL概述
    POI操作Excel常用方法总结
    段的创建表user_segments
    定位导致物化视图无法快速刷新的原因
    在shell脚本中调用sqlplus
    Oracle 字符集的查看和修改
    Java Web发布
    JSP搭建
    完全卸载oracle11g步骤:
    剑指offer——二叉排序树(BST)、平衡二叉树(AVL)
  • 原文地址:https://www.cnblogs.com/g15009428458/p/12098925.html
Copyright © 2020-2023  润新知