进程池与线程池,协程

一:引子:基于多线程实现套接字服务端并发。如图1:

                 但是如图1这种基于多线程实现套接字服务端并发实现后,如果开启的客户端过多,那么服务端就会不停地开启线程,

           占用内存空间,所以不能这样无限的去开启线程 / 进程,所以需要采取一种措施,把并发的线程数 / 进程数控制在一定数量

           之内,从而阻止无限的去开启线程 / 进程,这样就引出了进程池与线程池。

二:进程池与线程池:池就是一个容器,来盛放线程/进程。

       进程池:

                        所以,当并发的任务数超过了机器所能承受的范围,就需要这个池,也就是这个容器来限制并发的

    个数(线程数/进程数),至于池里面是盛放进程还是线程,这就取决于并发的任务是IO密集型还是计算密集型。:

          1:如何使用进程池以及线程池:

                                  通过导入模块from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor,简单的

       进程池就造好了,如图2:

                      进程池完成后就需要提交任务,所以,提交任务的两种方式:

                                           ①:同步调用(如图4):提交完一个任务之后,就在原地等待,等待任务完完整整地运行完毕拿到结果后,

          再执行下一行代码,会导致任务是串行执行的。

                                           ②:异步调用(如图3):提交完一个任务之后,不在原地等待,而是直接执行下一行代码,会导致任务是

       并发执行的,异步调用通常和回调函数一起配合使用,结果(future对象)会在任务运行完毕后自动传给回调函数。

                                  但是(如图3)这种情况异步提交之后,没有显示结果,可以通过异步提交之后会有一个返回对象(如future),

                              这个对象下面有一个绑定方法result,来进行查看,这种形式就成了串行,也就成了同步调用(如图4)。

                                                   而异步提交只提交任务,不立即拿结果,而是任务全部提交完之后,再拿结果(如图5)。这就需要

      利用shutdown(wait=True)来实现,它的含义是:关闭进程池的入口,并且在原地等待进程池内所有任务运行完毕。

        进程池:最终如图6:

                                               

        线程池:如图7,和进程池类似,进程池是主进程操作回调函数,线程池是谁是空闲状态谁就操作回调函数。

三:协程

           1:协程就是在单线程下实现并发

                       并发(多个任务看起来是同时执行就是并发),并发的核心:切换+保存状态

                 注意:协程是程序员自己定义出来的东西,操作系统里只有进程和线程的概念(操作系统调度的是线程)

                 当然,单线程下实现并发并不是都有意义的,只有在单线程下实现多个任务间遇到IO就切换就可以降低单线程的IO时间,

       从而最大限度地提升单线程的效率。

            2:基于yield实现协程:(如图8)这种yield实现的协程,并不是遇到IO就切换,效率反而会降低了。由于yield不能

                  实现监测IO,遇到IO就进行切换的功能。所以现在需要找到一种方案,既能够管理单线程下的多个任务,又能识别

                  单线程任务下的IO行为,实现遇到IO就自动能切换到另一个任务去运行,从而实现单线程下的并发,提升效率。

                  这就是gevent模块。

            3:gevent模块:gevent模块的使用如图9:

            4:利用gevent模块实现单线程下并发的套接字通信,如图10:

         

   

   

                 

猜你喜欢

转载自www.cnblogs.com/duanxiangyang/p/9621260.html
今日推荐