多进程
开启单一进程
主要是通过from multiprocessing import Process
启动进程任务,其接口参数为:
- group:进程所属组,基本不用
- target:表示调用对象, 为可调用对象(func)
- args:表示调用对象的位置参数元组,args = (i,) 传入一定是 tuple 格式,即便是单个参数
- name:别名
- kwargs:表示调用对象的字典。
创建完process对象以后,并用其**start()**方法启动进程,join()方法表示等待子进程结束以后再继续往下运行,主要用于阻塞主进程,通常用于进程间的同步。
from multiprocessing import Process
class MyProcess(Process):
def __init__(self,name = ''):
super(MyProcess,self).__init__()
self.name = name
def run(self):
print("Process num is : %s" % self.name)
time.sleep(1)
print('process %s end' % self.name)
def doIt(num):
print("Process num is : %s" % num)
time.sleep(1)
print('process %s end' % num)
def _tst2():
ps = []
print('mainProcess start')
start_time = time.time()
# for i in range(3):
# process = MyProcess(name = str(i))
# process.start()
# ps.append(process)
for i in range(5):
process = Process(target=doIt,args=(i,))
process.start()
ps.append(process)
for p in ps:
p.join()
print('mainProcess done time:%s s' % (time.time() - start_time))
'''
mainProcess start
Process num is : 0
Process num is : 1
Process num is : 2
Process num is : 3
Process num is : 4
process 0 end
process 1 end
process 2 end
process 3 end
process 4 end
mainProcess done time:1.0101220607757568 s
'''
开启进程池
当被操作对象数目不大时,可以直接利用multiprocessing中的Process动态成生多个进程,十几个还好,但如果是上百个,上千个目标,手动的去限制进程数量却又太过繁琐,此时可以发挥进程池的功效。
Pool可以提供指定数量的进程供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来它。
- apply(): 阻塞主进程, 并且一个一个按顺序地执行子进程, 等到全部子进程都执行完毕后 ,继续执行 apply()后面主进程的代码
- apply_async() 非阻塞异步的, 他不会等待子进程执行完毕, 主进程会继续执行, 他会根据系统调度来进行进程切换
import time
import multiprocessing
def doIt(num):
print("Process num is : %s" % num)
time.sleep(1)
print('process %s end' % num)
if __name__ == '__main__':
print('mainProcess start')
#记录一下开始执行的时间
start_time = time.time()
#创建三个子进程
pool = multiprocessing.Pool(3)
print('Child start')
for i in range(5):
pool.apply(doIt,[i]) # 进程池跑满后,会等待任务完成,才会开启新的任务
print('mainProcess done time:%s s' % (time.time() - start_time))
'''
mainProcess start
Child start
Process num is : 0
process 0 end
Process num is : 1
process 1 end
Process num is : 2
process 2 end
Process num is : 3
process 3 end
Process num is : 4
process 4 end
mainProcess done time:5.12246298789978 s
'''
- close(): 关闭进程池(pool),使其不在接受新的任务。
- terminate(): 结束工作进程,不在处理未处理的任务。
- join() 主进程阻塞等待子进程的退出,join方法必须在close或terminate之后使用。
执行结果 我们可以看到, 主进程开始执行之后, 创建的三个子进程也随即开始执行, 主进程被阻塞, 这里跟上一篇文章介绍的join() 很类似, 而且接下来三个子进程是一个接一个按顺序地执行, 等到子进程全部执行完毕之后, 主进程就会继续执行, 打印出最后一句;
接下来是使用apply_async(), 我们来看看运行结果 ,截图的第一句是上一个程序的执行消耗时间, 最后一句是使用apply_async() 所消耗的时间, 在这里, 主进程没有被阻塞, 验证了他是非阻塞的, 子进程没有执行, 验证了他是根据系统调度完成的, 为什么会这样呢?
原因是, 进程的切换是操作系统控制的, 我们首先运行的是主进程, 而CPU运行得又很快, 快到还没等系统调度到子线程, 主线程就已经运行完毕了, 并且退出程序. 所以子进程就没有运行了.
那么 调用了apply_async() 是不是就不能运行子进程了呢, 肯定可以呀!!小老弟,想啥呢??
还记得上一篇join()告诉主进程老子要运行子进程就好呀, 还记得 join()的作用吗, 我们从上一篇介绍join()的文章可以知道他可以阻塞主进程, 等待所有子进程结束之后再运行,
pool.close()
pool.join()
print('mainProcess done time:%s s' % (time.time() - start_time))
'''
mainProcess start
Child start
Process num is : 0
Process num is : 1
Process num is : 2 # 异步非阻塞,同时跑满进程池
process 0 end
process 1 end
Process num is : 3 # 进程池资源可继续开启新任务
Process num is : 4
process 2 end
process 3 end
process 4 end
mainProcess done time:2.0544939041137695 s
'''
# 如果不加join函数,那么还没等到系统调用子进程,主进程已经结束,那么就不会启动 子进程任务,所以需要使用join函数阻塞主进程,等待子进程运行完毕,再继续运行
多线程
Python3 通过两个标准库 _thread
和 threading
提供对线程的支持。
_thread 提供了低级别的、原始的线程以及一个简单的锁,它相比于 threading 模块的功能还是比较有限的。
threading 模块除了包含 _thread 模块中的所有方法外,还提供的其他方法:
- threading.currentThread(): 返回当前的线程变量。
- threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
- threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
除了使用方法外,线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:
class MyThread(threading.Thread):
def __init__(self,name = ''):
super(MyThread,self).__init__()
self.name = name
def run(self):
pass
- run(): 用以表示线程活动的方法。
- start():启动线程活动。
- join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
- isAlive(): 返回线程是否活动的。
- getName(): 返回线程名。
- setName(): 设置线程名。
import time
import threading
class MyThread(threading.Thread):
def __init__(self,name = ''):
super(MyThread,self).__init__()
self.name = name
def run(self):
print("Thread num is : %s" % self.name)
time.sleep(1)
print('Thread %s end' % self.name)
def doIt(num):
print("Process num is : %s" % num)
time.sleep(1)
print('process %s end' % num)
def _tst3():
ts = []
print('mainThread start')
start_time = time.time()
# for i in range(3):
# thread = MyThread(name = str(i))
# thread.start()
# ts.append(thread)
for i in range(3):
thread = threading.Thread(target=doIt,args=(i,))
thread.start()
ts.append(thread)
for t in ts:
t.join()
print('mainThread done time:%s s' % (time.time() - start_time))
完整的实例代码
import time
import multiprocessing
from multiprocessing import Process
import threading
class MyProcess(Process):
def __init__(self,name = ''):
super(MyProcess,self).__init__()
self.name = name
def run(self):
print("Process num is : %s" % self.name)
time.sleep(1)
print('process %s end' % self.name)
class MyThread(threading.Thread):
def __init__(self,name = ''):
super(MyThread,self).__init__()
self.name = name
def run(self):
print("Thread num is : %s" % self.name)
time.sleep(1)
print('Thread %s end' % self.name)
def doIt(num):
print("Process num is : %s" % num)
time.sleep(1)
# for _ in range(1000000000):
# x = 10*10
print('process %s end' % num)
def _tst1():
print('mainProcess start')
start_time = time.time()
pool = multiprocessing.Pool(3) # #创建三个子进程
print('Child start')
for i in range(5):
pool.apply_async(doIt,args=(i,)) # 进程池跑完后,会等待任务完成,才会开启新的任务
pool.close() # 关闭进程池,不在添加新任务
pool.join()
print('mainProcess done time:%s s' % (time.time() - start_time))
def _tst2():
ps = []
print('mainProcess start')
start_time = time.time()
# for i in range(3):
# process = MyProcess(name = str(i))
# process.start()
# ps.append(process)
for i in range(5):
process = Process(target=doIt,args=(i,))
process.start()
ps.append(process)
for p in ps:
p.join()
print('mainProcess done time:%s s' % (time.time() - start_time))
def _tst3():
ts = []
print('mainThread start')
start_time = time.time()
# for i in range(3):
# thread = MyThread(name = str(i))
# thread.start()
# ts.append(thread)
for i in range(3):
thread = threading.Thread(target=doIt,args=(i,))
thread.start()
ts.append(thread)
for t in ts:
t.join()
print('mainThread done time:%s s' % (time.time() - start_time))
if __name__ == '__main__':
_tst2()
_tst3()