多应用任务
def func1(n):
for i in range(n):
print('搬砖',i)
yield None
def func2(n):
for i in range(n):
print('听歌',i)
yield None
g1 = func1(3)
g2 = func2(3)
while True:
try:
g1.__next__()
g2.__next__()
except:
break
线程和进程
并发和并行
- 并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔内发生。
- 并发:CPU运行时间划分成若干个时间段,再将时间段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状。
- 并行:当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行
实现多任务的方式
- 多进程
- 多线程
- 协程
- 进程>线程>协程
进程
创建进程
-
首先导入Process
from multiprocessing import Process
-
Process(target=函数,name=进程的名字,args=(向函数传递的参数,可迭代的对象))
-
对于进程对象process
-
process.start()执行任务并启动进程
-
process.run()执行任务但不启动进程
-
process.terminate()终止
-
from multiprocessing import Process
from time import sleep
import os
def task1(s,name):
while True:
sleep(s)
print('task1``````````````',os.getpid(),'·······················',os.getppid(),name)
def task2(s,name):
while True:
sleep(s)
print('task2````````````````',os.getpid(),'··················',os.getppid(),name)
if __name__ == '__main__':
p1 = Process(target=task1,name='rw1',args=(1,'aa'))#子进程
p1.start()
print(p1.name)#主进程所做的
p2 = Process(target=task2,name='ew2',args=(2,'bb'))# 子进程
p2.start()
print(p2.name)
n = 1
while True:
n+=1
sleep(0.2)
if n == 5:
p1.terminate()
print('p1 stop')
break
else:
print(n)
- 多进程对于全局变量访问,在每一个全局变量里都放一个m变量 保证每个进程访问变量互相不干扰
- 对于不可变的变量还是可变变量都是一样的效果
from multiprocessing import Process
from time import sleep
m=0 #不可变类型
list1=[] #可变类型
def task1():
while True:
sleep(1)
global m
m+= 1
list1.append(str(m)+'t1')
print('task1``````````````',m,list1)
def task2():
while True:
sleep(2)
global m
m+= 1
list1.append(str(m) + 't2')
print('task2````````````````',m,list1)
if __name__ == '__main__':
p1 = Process(target=task1,name='rw1')
p1.start()
p2 = Process(target=task2,name='ew2')
p2.start()
while True:
sleep(1)
m+=1
print('main:',m)
自定义进程
继承Process类,并根据需求重写方法
from multiprocessing import Process
class MyProcess(Process):
#重写run方法
def __init__(self,name):
super(MyProcess,self).__init__()
self.name=name
def run(self) :
n=1
while True:
# print('进程名:',self.name)
print('---------------->自定义进程,n=',n,self.name)
n+=1
if __name__ == '__main__':
p = MyProcess('xiaom')
p.start()
进程池
- 可以自己设置进程数。
- 可以复用。任务数>池中位置数,当一个任务结束后,会自动加入一个新的任务。
- pool=Pool(n)创建进程池
- pool.close()任务添加结束
- pool.join()插队,让主进程给自己让路
阻塞式
使用apply()一个一个来,一个一个的完成,一个一个的返回。一个不完成,另一个不加入。没有回调函数
from multiprocessing import Pool
import time
import random
import os
def task(name):
print('start:',name)
st= time.time()
time.sleep(random.random())
end = time.time()
print('work:{},time:{},id:{}'.format(name,(end-st),os.getpid()))
# return 'work:{},time:{},id:{}'.format(name,(end-st),os.getpid())
container = []
def callback_func(n):
container.append(n)
if __name__ == '__main__':
pool=Pool(3)
tasks = ['game','movie','sleep','keep','work']
for t in tasks:
pool.apply(task,args=(t,))
pool.close()#任务添加结束
pool.join()#插队
for c in container:
print('callback:',c)
print('over')
"""
start: game
work:game,time:0.2110910415649414,id:13040
start: movie
work:movie,time:0.9919724464416504,id:11200
start: sleep
work:sleep,time:0.04570508003234863,id:3120
start: keep
work:keep,time:0.9166526794433594,id:13040
start: work
work:work,time:0.26379990577697754,id:11200
over
"""
非阻塞式
使用apply_async()全部添加到队列,立刻返回,并没有等待其他进程完毕,回调函数等待全部任务完成后才调用。
from multiprocessing import Pool
import time
import random
import os
def task(name):
print('start:',name)
st= time.time()
time.sleep(random.random())
end = time.time()
return 'work:{},time:{},id:{}'.format(name,(end-st),os.getpid())
container = []
def callback_func(n):
container.append(n)
if __name__ == '__main__':
pool=Pool(3)
tasks = ['game','movie','sleep','keep','work']
for task1 in tasks:
pool.apply_async(task,args=(task1,),callback=callback_func)
pool.close()#任务添加结束
pool.join()#插队
for c in container:
print('callback:',c)
print('over')
"""
start: game
start: movie
start: sleep
start: keep
start: work
callback: work:sleep,time:0.168532133102417,id:19648
callback: work:keep,time:0.45188164710998535,id:19648
callback: work:game,time:0.712028980255127,id:11288
callback: work:movie,time:0.8986353874206543,id:15052
callback: work:work,time:0.8844568729400635,id:19648
over
"""
进程间的通信
使用Queue
- q = Queue(n) 创建长度为n的队列
- full() 判断队列是否满了
- empty() 判断是否空
- put() 向队列中添加值,如果queue满了就只能等待,除非有空地才能添加成功
- get() 在队列中取值,如果空了就等待
from multiprocessing import Queue
q = Queue(3)
q.put('1')
q.put('2')
q.put('3')
print(q.qsize())
if not q.full():
q.put('4', timeout=2)
else:
print('full')
print(q.get(timeout=1))
print(q.get(timeout=1))
print(q.get(timeout=1))
if not q.empty():
print(q.get(timeout=1))
else:
print('empty')
"""
3
full
1
2
3
empty
"""
进程中的通信通过传值进行
from multiprocessing import Process
from multiprocessing import Queue
from time import sleep
def download(q):
img = ['a.jpg','b.jpg','c.jpg']
for i in img:
print('downloading:',i)
sleep(0.5)
q.put(i)
def grtfile(q):
while True:
try:
file = q.get()
print('finish:',file)
except:
print('done')
break
if __name__ == '__main__':
q = Queue(3)
p1 = Process(target=download,args=(q,))
p2 = Process(target=grtfile,args=(q,))
p1.start()
p1.join()
p2.start()
p2.join()
"""
downloading: a.jpg
downloading: b.jpg
downloading: c.jpg
finish: a.jpg
finish: b.jpg
finish: c.jpg
Process finished with exit code -1
"""