Python 多进程

多进程

开启单一进程

主要是通过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 通过两个标准库 _threadthreading 提供对线程的支持。

_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()



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值