进程 :
进程池
线程 :
理论
threading.Thread来创建线程
1 . 下面代码是同步请求的
import os,time
from multiprocessing import Pool
def wahaha()
time.sleep(1)
print(os.getpid())
return True
if __name__ == "__main__":
p = Pool(5)
li = []
for i in range(10):
ret = p.apply(func=wahaha) #同步的,不用
print(ret)
2 . 异步提交 , 不获取返回值
import os,time
from multiprocessing import Pool
def inner():
time.sleep(1)
print(os.getpid())
if __name__ == "__main__":
p = Pool(5) #进程池里的进程个数一般是CPU的个数,或者 + 1.
for i in range(10):
ret = p.apply_async(func=inner) #async 异步的
p.close() #关闭了进程池,让任务不能再继续提交了
p.join() #等待这个池中提交的任务都执行完,急等待所有子进程的代码都执行完,主进程才结束
3 . 异步提交,获取返回值,等待所有任务都执行完毕之后再统一获取结果
import os,time
from multiprocessing import Pool
def inner():
time.sleep(1)
print(os.getpid())
return True
if __name__ == "__main__":
p = Pool(5)
li = []
for i in range(10):
ret = p.apply_async(func=inner)
li.append(ret)
p.close()
p.join()
for ret in li:
print(ret.get())
4 . 异步提交,获取返回值,一个任务执行完毕之后就可以获取到一个结果(顺序是按照提交任务的顺序)
import os,time
from multiprocessing import Pool
def inner():
time.sleep(1)
print(os.getpid())
return True
if __name__ == "__main__":
p = Pool(5)
li = []
for i in range(10):
ret = p.apply_async(func=inner)
li.append(ret)
for ret in li:
print(ret.get())
异步的 apply_async
1 . 如果是异步得提交任务,那么任务提交之后进程池和主进程池也异步了,主进程不会自动等待进程池中的任务执行完毕
2 . 如果需要主进程等待,需要 p.join 但是join的行为是依赖close的
3 . 如果这个函数是有返回值的,也可以通过ret.get()来获取返回值,但是如果一边提交一遍获取返回值会让程序变成同步的;所以要想保留异步的效果,应该将返回对象保存在列表里,所有任务提交完成之后再来取结果,这种方式也可以去掉join,来完成主进程的阻塞等待池中的任务执行完毕.
回调函数
import os,time,random
from multiprocessing import Pool
def wrapper(num):
time.sleep(random.random())
print("pid :",os.getpid(),num)
return num
def back(arg):
print("call_back:",os.getpid(),arg)
if __name__ == "__main__":
print("主进程",os.getpid())
p = Pool(5)
for i in range(10):
ret = p.apply_async(func=wrapper,args=(i,),callback=back)
p.close()
p.join()
回调函数 : 在主进程中执行
在发起任务的时候,指定callback参数
在每个进程执行完apply_async任务之后,返回值会直接作为参数传递给callback的函数,执行callback函数中的代码
回调函数的用处 : 如果有两个任务,我的第二个任务在第一个任务执行完毕之后能够立即被主进程执行.
进程 :
是计算机中最小的资源分配单位
在利用多个CPU执行的过程中,对多个程序的资源进行管理和隔离
进程的弊端 :
开启和关闭以及切换都会带来很大的时间开销
过多的进程还会造成操作系统调度的压力
线程 :
线程是CPU调度的最小单位
每个线程中至少有一个线程
实际上执行代码的是线程
线程属于进程 :
线程不能独立存在,必须在一个进程里
进程负责获取操作系统分配给自己的资源,线程负责执行代码
从代码的角度上来看 :
多进程 :
开启和结束时间开销大 , 切换的效率低 , 内存隔离
多线程 :
开启和结束时间开销非常小 , 切换效率高 , 内存不隔离
Cpython解释器下的全局解释器锁 :
在同一个进程中的多个线程在同一时刻只能有一个线程访问CPU
多线程无法形成并行 ,使的一个进程中的多个线程不能充分利用多核.
全局解释器锁,锁的是线程
什么时候才会用到CPU?
程序计算的时候
IO阻塞, 是不会用到CPU的
Jpython解释器就没有全局解释器锁
pypy解释没有全局解释器锁
一台机器中有4个CPU 最多能同时执行四个进程 , 进程里起线程
threading模块初识
import os,time
from threading import Thread
def func():
time.sleep(1)
print(123,os.getpid())
print(123,os.getpid())
for i in range(10):
Thread(target=func).start()
线程好还是进程好 ? == 什么时候用进程, 什么时候用线程?
CPU的使用率 : 计算 --------多进程
IO操作 : 网络/文件/数据库 -------- 多线程
又有计算 , 又有IO操作--------------进程 + 线程