|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 Stubborn 于 2019-3-11 23:58 编辑
多任务介绍(例如你需要运行多个软件,QQ,微信,浏览器,视频软件)
单核CPU的多任务实现:操作系统轮流让每个任务交替执行
多核CPU的多任务实现:真正的秉性执行多任务只能在多核CPU上实现,但由于任务数量远远多于CPU的核心数,所以操作系统也会自动把多个任务轮流调度到每个CPU核心上
并发:看上去一起执行,任务数多于CPU核心数
并行:真正一起执行,任务数小于等于CPU核心数
实现多任务的方式:
A进程:
对于系统而言,一个任务就是一个进程
进程是系统中程序执行和资源分配的基本单位。每个进程都有自己的数据段,代码段,和堆栈段。
A.1==>单任务
如下代码,只有一个主进程,执行到死循环,并不会反复执行run函数,
- from time import sleep
- def run():
- while True:
- print("sunck is a nice man")
- sleep(1)
- if __name__ == '__main__':
- while True: #任务1
- print("sunck is a good man")
- sleep(1)
- #不会执行到run方法,只有上面的while循环结束,才可以执行
- run()
复制代码
A.2==>启动多进程(同时执行任务与1任务2)
multiprocessing 库
跨平台的多进程模块,提供一个Process类来代表一个进程类对象
如代码块是上一个代码修改,加多一个子进程用来执行run函数,此时代码里面主进程在执行到死循环,子进程执行到run函数里面的死循环
- from multiprocessing import Process
- from time import sleep
- import os
- def run(str):
- while True:
- #os.getpid()获取当前进程ID号
- #os.getppid()获取当前父进程的ID
- print("sunck is a %s man---%s---%s"%(str,os.getpid(),os.getppid()))
- sleep(1)
- if __name__ == '__main__':
- print("主(父)进程启动----%s"%(os.getpid()))
- #创建一个子进程
- #target说明进程执行的任务(任务1run)
- #args 需要传递的参数
- p = Process(target=run,args=("nice",))
- #启动进程
- p.start()
- while True: #任务2
- print("sunck is a good man")
- sleep(1)
复制代码
A.3==>父与子进程顺序
如果没有join(),那么主进程会直接结束掉,以为程序执行完毕。但是我们需要的是子进程为我们继续处理,或者运行。所以需要主进程等待子进程运行或者处理完毕之后在结束主进程
- from multiprocessing import Process
- from time import sleep
- import os
- def run(str):
- print("启动子线程")
- sleep(3)
- print("结束子线程")
- if __name__ == '__main__':
- print("主(父)进程启动----%s"%(os.getpid()))
- p = Process(target=run,args=("nice",))
- p.start()
- #父进程的结束不能影响子进程
- #让父进程等待子进程结束,再执行父进程
- p.join()
- print("父进程结束")
复制代码
A.4==>全局变量在多进程中,不会共享
每个进程都有自己的数据段,代码段,和堆栈段。
在子线程中对全局变量进行修改,对父进程中的全局变量没有影响
在创建子进程时对全局变量做了一个备份,父与子进程中的num是2个完全不同的变量
- from multiprocessing import Process
- import os
- num = 100
- def run(str):
- print("启动子线程")
- global num
- num += 1
- print("结束子线程")
- if __name__ == '__main__':
- print("主(父)进程启动----%s"%(os.getpid()))
- p = Process(target=run,args=("nice",))
- p.start()
- #让父进程等待子进程结束,再执行父进程
- p.join()
- print("父进程结束---%d"%(num))
复制代码
A.5==>开辟大量子进程
- from multiprocessing import Pool
- import os,random,time
- 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:进程池 默认大小是CPU核心数
- pp = Pool()
- for i in range(17): #rang()大于CPU核心数,或者线程池数
- #数量小于CPU核心,会同时启动,数量大于CPU核心,分批轮流启动
- #子线程执行没有顺序
- #创建进程,放入进程池统一管理
- pp.apply_async(run,args=(i,))
- #使用进程池,在调用join,必须先调用close,调用close不能添加新的进程
- pp.close()
- #进程池对象调用join,会等待经常池中所有的子进程结束在去执行父进程
- pp.join()
- print("父进程结束---"
复制代码
A.5.1==>开辟大量子进程,用于copy文件。函数与进程:
注:当文件比较小的时候,直接用函数copy比较快,因为开辟大量子进程比较消耗时间
- import os,time
- from multiprocessing import Pool
- # 循环函数实现
- # def copyFile(rpath,wpath):
- # "copy文件"
- # fr = open(rpath,"rb")
- # fw = open(wpath,"wb")
- # fw.write(fr.read())
- # fr.close()
- # fw.close()
- # rpath = r"C:\Users\Stubbron\Desktop\进程,线程\进程\file"
- # wpath = r"C:\Users\Stubbron\Desktop\进程,线程\进程\Tofile"
- # filelsit = os.listdir(rpath)
- # start = time.time()
- # for filename in filelsit:
- # copyFile(os.path.join(rpath,filename),os.path.join(wpath,filename))
- # end = time.time()
- # print("耗时:%.2f"%(end-start)) #耗时:7.46 copy 1.54文件
- def copyFile(rpath,wpath):
- "copy文件"
- fr = open(rpath,"rb")
- fw = open(wpath,"wb")
- fw.write(fr.read())
- fr.close()
- fw.close()
- rpath = r"C:\Users\Stubbron\Desktop\进程,线程\进程\file"
- wpath = r"C:\Users\Stubbron\Desktop\进程,线程\进程\Tofile"
- if __name__ == '__main__':
- filelsit = os.listdir(rpath)
- start = time.time()
- pp = Pool()
- for filename in filelsit:
- pp.apply_async(copyFile,args=(os.path.join(rpath,filename),os.path.join(wpath,filename)))
- pp.close()
- pp.join()
- end = time.time()
- print("耗时:%.2f" % (end - start)) #耗时:4.85 copy 1.54文件
复制代码
A.6==>封装进程对象
对封装进程对象的代码块可以单独写在一个模块,代码看起来比较整洁,也方便日后代码重构
- from multiprocessing import Process
- import os
- class StubbronProcess(Process):
- def __init__(self,name):
- Process.__init__(self)
- self.name = name
- def run(self):
- print("子进程(%s--%s)启动"%(self.name,os.getpid()))
- #子进程的功能
- print("子线程要去干啥")
- print("子进程(%s--%s)结束" % (self.name, os.getpid()))
- if __name__ == '__main__':
- print("父进程启动")
- #创建子进程
- p = StubbronProcess("test")
- #自动调用p进程对象的run方法
- p.start()
- p.join()
- print("父进程结束")
复制代码
A.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()
- writ = Process(target=write,args=(q,))
- rea = Process(target=read,args=(q,))
- writ.start()
- rea.start()
- writ.join()
- #rea进程里是个死循环,无法等待其结束 ,只能强行结束
- rea.terminate()
- print("父进程结束")
复制代码
|
|