python之进程_线程_协程 总结

目录

   0. 前言
   1. 进程学习总结
       1.1 进程的理解
       1.2 进程的三种状态
       1.3 multiprogressing模块
         1.3.1 Process类
         1.3.2 current_process
         1.3.3 active_children
         1.3.4 Queue客户
         1.3.5 Pool类
         1.3.6 Manager().Queue()
   2. 线程学习总结
       2.1 线程的理解
       2.2 threading模块
         2.2.1 Thread类
         2.2.2 Lock类
         2.2.3 enumerate
         2.2.4 current_thread
         2.2.5 active_count
       2.3 线程池实现: multiprogressing.dummy模块
   3. 协程学习总结
       3.1 协程理解
       3.2 协程详解及实现
          3.2.1 yield实现
          3.2.2 greenlet模块
          3.2.3 gevent模块
       3.3 协程池实现: gevent.pool模块
   4. 结束语


0. 前言

回到顶部👆

  在日常工作中经常会碰到并发执行的问题,免不了要和各类python模块打交道,在此记录下自己的理解,方便以后重拾。


1. 进程学习总结

回到顶部👆

1.1 进程的理解

回到顶部👆

  1. 进程是操作系统进行资源分配和调度的基本单位;
  2. 一个运行起来的软件/程序叫一个进程,进程只提供运行资源,真正干活的是线程;
  3. 不同进程之间不共享任何状态,每个进程都有自己独立的内存空间,进程间的通讯需要通过操作系统执行信号的传递(queue).
1.2 进程的三种状态

回到顶部👆


就绪态:运行的条件都已经满足,正在等cpu调度执行;
执行态:cpu正在执行其功能;
等待态度:等待某些条件满足,例如一个程序sleep了,此时就处于等待态;

1.3 multiprocessing模块

回到顶部👆

1.3.1 Process类

回到顶部👆

参数:target/name/ages/kwargs/group;
is_alive(): 判断进程是否活着;
start(): 开始进程;
join(): 进程等待;
daemon: 属性,守护进程;
terminate(): 立即终止进程,只在子进程外使用;

1.3.2 current_process()

回到顶部👆

获取进程编号: current_process().pid[当前] os.getpid()[当前] os.getppid()[父进程];
杀死进程: os.kill(is.getpid(), signal.SIGKILL/9);

1.3.3 active_children()

回到顶部👆

获取当前活动的子进程;

1.3.4 Queue类

回到顶部👆

进程间通讯(先进先出):
参数: 上限数据个数,不写/负数则无上限[multiprocessing.Queue(3)];
put()/get(): 放入/获取[有阻塞功能;参数:内容,是否阻塞,阻塞时间]:
   put(‘消息’, True, 2) / put(‘消息’, False);
   get(True, 2)/get(False);
put_nowait()/get_nowait(): 放入/获取[不会阻塞,会报错]:
   put_nowait(‘消息’) 等价于 put(‘消息’, False);
   get_nowait() 等价于 get(False);
full(): 是否满了;
empty(): 是否空了;
qsize(): 队列中数据个数;

1.3.5 Pool类

回到顶部👆

参数: 上限进程个数;
apply()/apply_sync(): 同步/异步执行;
close(): 关闭Pool,不再接受新功能,进程池关闭;
terminate(): 不管任务是否完成,立即终止;
join(): 进程池等待,必须用在close/terminate之后;

1.3.6 Manager().Queue()

回到顶部👆

进程池中的进程间通讯,用法同Queue();


2. 线程学习总结

回到顶部👆

2.1 线程理解

回到顶部👆

  1. 进程的一个实体,是cpu调度和分派的基本单位;
  2. 同一个进程内的不同线程,共享同一个进程内的内存空间;
  3. 线程之间切换开销小,通讯效率高,可以共享内存空间;
  4. GIL(全局解释器锁): 程序执行活动中,一次只能执行一个线程;
       好处: 直接杜绝了多个线程同时访问进程内存空间的安全问题;
       坏处: python中的多线程并不是真正的多线程,一次只能执行一个线程,不能充分利用cpu多核资源;
  5. 缺点: 同一时间内存一次只能运行一个线程,可以做到并发,不能做到并行;
  6. 使用场景: IO密集任务(网络IO、磁盘IO、数据库IO等);
2.2 threading 模块

回到顶部👆

2.2.1 Thread类

回到顶部👆

参数: target/name/args/kwargs/daemon/group;
start(): 线程开始执行[调用start()创建新线程,同时底层调用run()完成逻辑];
setDaemon(True): 守护主线程(主线程为主),主线程执行完,子线程立即结束[子线程start()之前设置];
join(): 线程等待(子线程为主),子线程执行完才执行主线程[子线程start()之后设置];
run(): 自定义线程类中,需要重写run()方法run()方法结束该线程就结束;

2.2.2 Lock类

回到顶部👆

创建锁: mutex = threadind.Lock()
上锁: mutex.acquire()
解锁: mutex.release()

2.2.3 enumerate()

回到顶部👆

当前活动线程列表[没启动的线程不算];

2.2.4 current_thread()

回到顶部👆

当前线程对象;

2.2.5 active_count()

回到顶部👆

活动线程数量;


2.3 线程池实现: multiprocessing.dummy模块

回到顶部👆

from multiprocessing.dummy import Pool

# 1.初始化线程池对象
pool = Pool()

# 2.通过pool.map()依次将list里每个元素传递给func处理,并通过多线程----异步执行;
# 参数: func(必须) list(必须)
return_list = pool.map(func, list)

# 通过pool.map_async()依次讲list里每个元素传递给func处理,并通过多线程异步执行;
# 将每个函数返回值放入列表,再传给callback执行;
pool.map_async(func, list, callback)

# 2.如果func不需要传参,可以使用apply(逐条处理)和apply_async(异步执行);
# 参数: func(必须) args(可选)
pool.apply(func, args)

# 将args参数传递给func,并接收返回值交给callback执行;
pool.apply_async(func, args, callback)

# 关闭线程池,线程等待
pool.close()
pool.join()

3. 协程学习总结

回到顶部👆

3.1 协程理解

回到顶部👆

  1. 微线程: 本质就是一个函数,不由操作系统调度(没有cpu切换开销);
  2. 在单个线程上切换执行多个函数任务,切换调度由程序员决定,不涉及操作系统管理,也不需要处理锁;
  3. 缺点: 单县城执行,不能处理密集cpu任务,本地磁盘IO密集任务;
  4. 使用场景: 网络密集IO任务;
3.2 协程详解及实现

回到顶部👆

3.2.1 yield实现

回到顶部👆

  1. 多个功能通过yield交替执行,模拟多线程;
  2. 缺点:
        死循环,没法执行次数;
        依旧单线程,只是模拟多任务;

使用方式如下:

# 创建生成器/协程
generator = func()
# 执行生成器/协程
next(generator)
3.2.2 greenlet模块

回到顶部👆

  1. 封装了yield,需要手动交替调用;
  2. 不能存在循环应用(官方文档明确说明);

使用方式如下:

# 创建协程
g1 = greenlet.greenlet(func)
# 协程开始
g1.switch()
3.2.3 gevent模块

回到顶部👆

  1. 封装了yield,自动交替调用;
  2. 不识别input(),涉及到尽量使用线程/进程;

使用方式如下:

# 打补丁
from gevent import monkey

monkey.patch_all()
# 创建协程
g = gevent.spawn(func)
# 协程等待
g.join()

# 2、3步合并写法
gevent.joinall([
    gevent.spawn(func, *args, **kwargs),
    gevent.spawn(func, *args, **kwargs),
])
3.3 协程池实现: gevent.pool模块

回到顶部👆

   用法和线程池一样,但是导包不同,协程池也不需要close();

from gevent.pool import Pool

# 1.导入协程patch_all()补丁,执行该补丁,则当前解释器环境的任务,全部按异步方式执行
from gevent import monkey
monkey.patch_all()

# 2.实例化协程池对象
pool = Pool(10)

# 3.异步执行任务,和线程池一样
pool.apply_async(send_request_func, args=(url,), callback=use_result)

# 4.线程等待,不需要close()
pool.join()

4. 结束语

回到顶部👆

   终于搞完了,累的一p,暂时只想到这些,先写这么多,以后想到什么再来附加吧。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值