多进程和多线程

<!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 查看子进程的编号
原文地址:https://www.cnblogs.com/g15009428458/p/12098925.html