1、启动进程实现多任务
现代操作系统(windows,Mac OS X ,Linux等)
多任务:操作系统可以运行多个任务
早期的cpu都是单核cpu实现多任务原理:操作系统轮流让各个任务交替执行,任务反复执行下去,但是cpu调度执行太快,导致感觉多有任务都在同时执行
多核cpu执行多任务原理:真正的并行执行多任务只能在多核cpu上实现,但是由于 任务数量远远超过cpu的核心数量,所以操作系统也会自动将很多任务轮流的调度到每个核心上执行
并发:看上去一起执行,任务数多余cpu核心数
并行:真正一起执行,任务书小于等于cpu核心数(效率最高)
实现多任务方式:
1、多进程模式
2、多线程模式
3、协程模式
4、多进程加上多线程模式
进程:
对于操作系统而言一个任务就是一个进程
进程是系统中程序执行和分配的基本单位,每个进程都有自己的数据段,代码段和堆栈段
单任务现象
from time import sleep
def run():
while True:
print("123")
sleep(1.2)
if __name__ == "__main__":
while True:
print("456")
sleep(1)
#不会执行这个方法只有等上面的while执行完才能执行
run()
启动进程实现多任务
from multiprocessing import Process
from time import sleep
import os
#子进程需要执行的代码
#os.getid获取当前进程的id号
#os.getppid获取当前进程的父进程的id号
def run(str):
while True:
print("sunck is a %s man--%s--%s "% (str, os.getpid(),os.getppid()))
sleep(1.2)
if __name__ == "__main__":
print("主进程启动--%s"%(os.getpid()))
# 创建一个子进程在主进程之前启动
# target说明进程的执行任务
p = Process(target=run,args=("nice",))
# 启动子进程
p.start()
while True:
print("456")
sleep(1)
2、启动多个子进程
from multiprocessing import Pool
import os,time,random
def run(name):
print("子进程%d开始--%s" % (name,os.getpid()))
start = time.time()
time.sleep(random.choice([1,2,3]))
end = time.time()
print("子进程%d结束--%s--耗时%.2f" % (name,os.getpid(),end-start))
if __name__ == "__main__":
print("父进程启动--%s" % (os.getpid()))
#创建多个进程
#Pool进程池
#4表示可以同时执行的进程数量,如果不写默认的是cpu核心数
pp = Pool(2)
#range中的数必须大于Pool中的数才能看出效果
for i in range(4):
#创建进程放入进程池统一管理
pp.apply_async(run,args=(i,))
#在调用join之前必须先调用close,并且调用close之后不能再继续添加新的进程了
pp.close()
#进程池对象调用join,会等待进程池中所有的子进程结束完毕再去执行父进程
pp.join()
print("父进程结束--%s" % (os.getpid()))
父进程启动--8008
子进程0开始--11692
子进程1开始--2996
子进程0结束--11692--耗时2.00
子进程2开始--11692
子进程1结束--2996--耗时3.00
子进程3开始--2996
子进程2结束--11692--耗时2.00
子进程3结束--2996--耗时2.00
父进程结束--8008
3、全局变量不能在多个子进程中共享
from multiprocessing import Process
num = 100
def run():
print("子进程开始")
global num
num += 1
print("%d" % num)
print("子进程结束")
if __name__ == "__main__":
print("父进程开始")
p = Process(target=run)
p.start()
p.join()
p2 = Process(target=run)
p2.start()
p2.join()
print("父进程结束--%d" % (num))
父进程开始
子进程开始
101
子进程结束
子进程开始
101
子进程结束
父进程结束--100
4、封装继承对象
from multiprocessing import Process
import os,time
class SunckProcess(Process):
def __init__(self,name):
Process.__init__(self)
self.name = name
def run(self):
print("子进程(%s-%s)启动"%(self.name,os.getpid()))
#子进程的功能
time.sleep(3)
print("子进程(%s-%s)结束" % (self.name, os.getpid()))
if __name__ == "__main__":
print("子进程启动")
#创建子进程
p = SunckProcess("test")
#自动调用进程对象
p.start()
p.join()
print("父进程结束")
5、父子进程的先后顺序
from multiprocessing import Process
from time import sleep
def run(str):
print("启动子进程")
sleep(3)
print("子进程结束")
if __name__ == "__main__":
print("父进程启动")
p = Process(target=run,args=("nice",))
p.start()
#父进程的结束不能影响子进程,让父进程等待子进程结束再执行父进程
p.join()
print("父进程结束")
6、用进程拷贝文件
import os,time
#拷贝文件def copyFile(rPath,wPath):
fr = open(rPath,"rb")
fw = open(wPath,"wb")
context = fr.read()
fw.write(context)
fr.close()
fw.close()
path = r"D:\py2"
toPath = r"D:\py3"
#读取path下所有的文件
start = time.time()
fileList = os.listdir(path)
for fileName in fileList:
copyFile(os.path.join(path,fileName),os.path.join(toPath,fileName))
end = time.time()
print("总耗时%.2f" % (end-start))
多进程拷贝文件比单进程快
from multiprocessing import Pool
import os,time
def copyFile(rPath,wPath):
fr = open(rPath,"rb")
fw = open(wPath,"wb")
context = fr.read()
fw.write(context)
fr.close()
fw.close()
path = r"D:\py2"
toPath = r"D:\py3"
7、进程间的通信
from multiprocessing import Process,Queue
import os,time
def write(q):
print("启动写子进程%s" % (os.getpid()))
for chr in ["A","B","C","D"]:
q.put(chr)
time.sleep(1)
print("结束写子进程%s" % (os.getpid()))
def read(q):
print("启动读子进程%s" % (os.getpid()))
while True:
value = q.get(True)
print("value = " + value)
print("结束读子进程%s" % (os.getpid()))
if __name__ == "__main__":
print("父进程启动")
#父进程创建队列,并传递给子进程
q = Queue()
pw = Process(target=write,args=(q,))
pr = Process(target=read,args=(q,))
pw.start()
pr.start()
pw.join()
#pr进程里面是个死循环,无法等待其结束,只能强行结束
pr.terminate()
print("父进程结束")