进程理论以及开启子进程的两种方式
进程理论(book:现代操作系统)
为何开启子进程需要放在main下面:因为运行到start他会向操作系统发起启动子进程的信号,然后操作系统会把整个代码块执行下,找到子进程要执行的任务,
代码运行到最下面,又执行了start,又重复执行一次。线程可以不放在main下面是因为线程不用导入主线程里的东西,他们共享资源。
进程就是一个正在运行的程序或者说是一个程序的运行过程。
pid process id 进程在操作系统里的身份证号
串行、并发、并行、多道技术
并发实现的本质:切换 + 保存状态
时间复用:占用cpu过长或者有另外一个优先级更高的任务抢走cpu
i/0操作 读写
time.sleep()本质和时间复用一样 睡觉时候操作系统会切换cpu。
八核:八个cpu
多核任务分配:比如5个任务,四核,先一个cpu分配一个,然后先遇到i/o或者一个程序占用时间过长
切换就新接一个任务,然后i/o执行完毕,就切换到任意一个空闲的cpu。
切换的时候先保存进度,单核可以继续切回来继续运行程序
同一个程序执行两次,也是开启了两个进程。
二 、开启子进程的两种方式
os.cpu_count() 查看电脑是几个处理器
multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模块threading的编程接口类似。
与线程不同,进程没有任何共享状态,进程修改的数据,改动仅限于该进程内。
子进程实现方式一(有注释)
方式一是我们常用的
# # # 方式一:
from multiprocessing import Process
import time
def task(x):
print('%s is running' %x)
time.sleep(3)
print('%s is done' %x)
if __name__ == '__main__':
# Process(target=task,kwargs={'x':'子进程'})
p=Process(target=task,args=('子进程',)) # 如果args=(),括号内只有一个参数,一定记住加逗号
# target表示调用对象,即子进程要执行的任务,args是调用对象的位置参数元组。
p.start() # 只是在操作系统发送一个开启子进程的信号,操作系统会申请开辟一个内存空间。
# 然后把父进程的数据拷贝给子进程,作为子进程的初始状态。
print('主')
子进程实现方式二
# 方式二:
from multiprocessing import Process
import time
class Myprocess(Process):
def __init__(self,x):
super().__init__()
self.name=x
def run(self):
print('%s is running' %self.name)
time.sleep(3)
print('%s is done' %self.name)
if __name__ == '__main__':
p=Myprocess('子进程1')
p.start() # p.run() # 自定义类向操作系统发送一个开启子进程的信号,操作系统会申请开辟一个内存空间。
# 然后把父进程的数据拷贝给子进程,作为子进程的初始状态。
print('主')
同时开启多个子进程
from multiprocessing import Process
import time
def task(x,n):
print('%s is running' % x)
time.sleep(n)
print('%s is done' % x)
if __name__ == '__main__': # 可以开启多个子进程
# Process(target=task,kwargs={'x':'子进程'})
p1 = Process(target=task, args=('子进程1',3)) # 如果args=(),括号内只有一个参数,一定记住加逗号
p2 = Process(target=task, args=('子进程2',5)) # 如果args=(),括号内只有一个参数,一定记住加逗号
p1.start() # 只是在操作系统发送一个开启子进程的信号
p2.start() # 只是在操作系统发送一个开启子进程的信号
print('主')
越是困难的事越要立即去做,这样收益才会最大!!!