目录python
# 第一种方式 from multiprocessing import Process import time def task(name): print(f'{name} is running') time.sleep(2) print(f'{name} is gone') if __name__ == '__main__': # 在Windows环境下,必须在main下开启子进程 p = Process(target=task, args=('meet',)) # args元组形式 建立一个进程对象 p.start() print("===主进程") """ 结果: ===主进程 meet is running meet is done """ # p.start():开启子进程的命令,通知操做系统在内存中开辟一个进程空间,将主进程的数据copy加载到子进程空间中,而后操做系统调用cpu去执行子进程。 开销较大,所以会先执行主进程的代码。
# 第二种方式 from multiprocessing import Process import time class MyProcess(Process): def __init__(self, name): super().__init__() # 重构父类的方法 self.name = name def run(self): # 必须写run() print(f'{self.name} is running') time.sleep(2) print(f"{self.name} is gone") if __name__ == '__main__': p = MyProcess('meet') # 默认执行run() p.start() # 开启子进程的命令 print("===主进程")
进程在内存中的惟一标识。linux
终端命令: tasklist # 查看计算机当前全部进程的pid面试
终端命令: tasklist|findstr pycharm # 查看pycharm的pidapp
代码 :异步
import os print(os.getpid()) # 查看当前进程的pid print(os.getppid()) # 查看父进程的pid
from multiprocessing import Process lst = [1, 2] def task(): lst.append(3) print(f'子进程的:{lst}') if __name__ == '__main__': p = Process(target=task) p.start() print(f'主进程的:{lst}') """ 主进程的:[1, 2] 子进程的:[1, 2, 3] """ # 主进程与子进程之间存在空间隔离。
join :让主进程等待子进程结束以后,再执行主进程。(让主进程阻塞)
from multiprocessing import Process import time def task(sec): print('is running') time.sleep(sec) print('is gone') if __name__ == '__main__': start_time = time.time() p1 = Process(target=task, args=(1,)) p2 = Process(target=task, args=(2,)) p3 = Process(target=task, args=(3,)) p1.start() p2.start() p3.start() # 同时开启 p1.join() print(f'p1时间:{time.time()-start_time}') # 1s多 p2.join() print(f'p2时间:{time.time()-start_time}') # 2s多 p3.join() print(f'p3时间:{time.time()-start_time}') # 3s多
from multiprocessing import Process import time def task(sec): print('is running') time.sleep(sec) print('is gone') if __name__ == '__main__': start_time = time.time() p1 = Process(target=task, args=(3,)) p2 = Process(target=task, args=(2,)) p3 = Process(target=task, args=(1,)) # 改变时间 p1.start() p2.start() p3.start() # 同时开启 p1.join() print(f'p1时间:{time.time()-start_time}') # 3s多 #阻塞 p2.join() print(f'p2时间:{time.time()-start_time}') # 3s多 p3.join() print(f'p3时间:{time.time()-start_time}') # 3s多
# 面试题:将下面代码优化 from multiprocessing import Process import time def task(sec): print('is running') time.sleep(sec) print('is gone') if __name__ == '__main__': start_time = time.time() p1 = Process(target=task, args=(1,)) p2 = Process(target=task, args=(2,)) p3 = Process(target=task, args=(3,)) p1.start() p2.start() p3.start() p1.join() p2.join() p3.join() print(f'运行时间:{time.time()-start_time}') # 3s多 # 上面代码优化: lst = [] for i in range(1,4): p = Process(target=task, args=(i,)) lst.append(p) p.start() for i in lst: i.join() print(f'运行时间:{time.time()-start_time}') # 错误的优化: for i in range(1,4) p = Process(target=task, args=(i,)) p.start() p.join() print(f'运行时间:{time.time()-start_time}')
p.terminate() # 结束子进程 p.is_alive() # 判断子进程是否活着 True/False p = Process(target=task, args=('meet',), age=18) # 给子进程对象添加一个age属性。 print(p.age) # 18
实际中,主进程只有等待子进程结束后,主进程才结束。优化
基于Unix环境(linux,macOS):操作系统
主进程时刻监测子进程的运行状态,当子进程结束后,一段时间内,才会将子进程回收。code
为何不立刻回收?对象
Unix针对上面的问题,提供了一种机制:进程
全部的子进程结束后,立马释放掉文件的操做连接、内存等的大部分数据,可是会保留一些内容:进程号、结束时间、运行状态,等待子进程监测、回收。
僵尸进程:子进程在结束后,主进程并无调用wait或waitpid获取子进程的状态信息,子进程仍然保留了一些描述内容,这种进程被称为僵尸进程。
危害:若是父进程不对僵尸进程进行回收(wait/waitpid),产生大量的僵尸进程,这样会占用内存,占用进程的pid号。
父进程因为某种缘由结束,但子进程还在运行中,则称这些子进程为孤儿进程。
回收机制:Unix中孤儿进程会被 init 进程回收,init 变成父进程。
僵尸进程解决方法:
直接杀死父进程。将全部僵尸进程变成孤儿进程,由 init进程回收。
# 子进程守护着主进程,只要主进程结束,子进程也跟着结束。 from multiprocessing import Process import time def task(name): print(f'{name} is running') time.sleep(2) print(f'{name} is gone') if __name__ == '__main__': p = Process(target=task, args=('meet',)) # 建立一个进程对象 p.daemon = True # 放在start前,不然会报错。 p.start() time.sleep(1) print("===主进程") """ meet is running ===主进程 """