协程, IO模型 和 非阻塞模型

(1):小知识点:                                    查找线程的线程号     from threading import  current_thread      ====>current_thread()  可以查到自己的线程号  

线程池中的回调函数是子线程调用的,和父线程没有关系
进程池中的回调函数是父进程调用的,和子进程没有关系      ,注意是父进程

一.协程:        ======> 是一个更加轻量级的单位,是组成线程的各个函数,由程序员去调度的.(注意:pyhton中底层都是用yield实现的)

********yield 只能实现单纯的切换函数和保存函数状态的功能******* 不能实现:当某一个函数遇到io阻塞时,自动的切换到另一个函数去执行**********

因为Cpython中有GIL锁,限制了同一时间点,只能执行一个线程,为了充分利用cpu的利用率,在单线程内,实现并发的效果,就出现了协程

然而实现并发的效果(切换+保存状态),就是要在单线程内解决多个任务函数如果遇到IO,马上自动切换到其他的任务函数去执行任务

二,  <1>greenlet模块      ===> 能简单实现函数与函数之间的切换, 但是遇到IO操作,不能自动切换到其他函数(一个函数执行一个函数)

    (1) 注册一下函数func,将函数注册成一个对象f1

       f1 = greenlet(func)

    (2) 调用func,使用f1.switch(),如果func需要传参,就在switch这里传即可

示例:   time.sleep(1)不影响函数的交叉实现

from greenlet import greenlet
import time
# greenlet 只是可以实现一个简单的切换功能,还是不能做到遇到IO就切换
# g1 = greenlet(func)   实例化一个对象
# g1.switch()  用这种方式去调用func函数
# 当使用switch调用func的时候,什么时候func会停止运行?
#   1 要么return      2 要么在func内部又遇到 switch

def eat(name):
    print('%s吃炸鸡'%name)
    time.sleep(2)
    f2.switch('小雪2')
    print('%s吃雪糕'%name)
    f2.switch()

def drink(name):
    print('%s喝啤酒'%name)
    f1.switch()
    print('%s喝可乐'%name)


f1 = greenlet(eat)
f2 = greenlet(drink)
f1.switch('小雪')
View Code

 <2>gevent模块:可以实现在某函数内部遇到IO操作,就自动的切换到其他函数内部去执行

     g = gevent.spawn(func,参数) 注册一下函数func,返回一个对象g   这里有个坑;那个函数先注册就先执行

     gevent.join(g) #等待g指向的函数func执行完毕,如果在执行过程中,遇到IO,就切换

     gevent.joinall([g1,g2,g3])#等待g1 g2 g3指向的函数func执行完毕

示例:

三,selet  和 poll  和 epoll的区别 ====>windows只能用selet     但是lunix三个都能使用

  select和poll有一个共同的机制,都是采用轮训的方式去询问内核,有没有数据准备好了

  select有一个最大监听事件的限制,32位机限制1024个事件,,6位机限制2048个事件

  poll没有,理论上poll可以开启无限大,1G内存大概够你开10W个事件去监听

  epoll是最好的,采用的是回调机制,解决了select和poll共同存在的问题,而且epoll理论上也可以开启无限多个监听事件

  

猜你喜欢

转载自www.cnblogs.com/laogao123/p/9550547.html