day40

(1)线程池和进程池的shutdown
(2)定时器Timer
(3)协程
(4)虚拟环境
(5)greenlet模块
(6)gevent模块
(7)asyncio模块
(8)IO模型
# 线程池shutdown
'''
from concurrent.futures import ThreadPoolExecutor
import time

pool = ThreadPoolExecutor(3)


def task(name):
    print(f'{name}begin...')
    time.sleep(2)
    print(f'{name}end...')


if __name__ == '__main__':
    for i in range(10):
        pool.submit(task, i)

    pool.shutdown(wait=True)        # 等待所有任务执行完成,并关闭线程池,不能再继续提交任务
    print('main......')
'''

# 定时器Timer
'''
from threading import Timer


def task(name):
    print(f'{name} is sb.')


if __name__ == '__main__':
    # t = Timer(2, task, args=('lh',))          # 本质是开启一个线程,延迟2s后执行
    t = Timer(2, task, kwargs={'name': 'lh'})
    t.start()
'''

# 协程
'''
# 协程是为了实现单线程下的并发,属于线程之下,解决的问题:保存状态+切换
# 协程是一个抽象的概念,实际并不存在。由程序员来控制,不让程序遇到IO,看上去就是实现并发
# import time
#
#
# def func1():
#     for i in range(10000000):
#         i += 1
#
#
# def func2():
#     for i in range(10000000):
#         i += 1
#
#
# if __name__ == '__main__':
#     ctime = time.time()
#     func1()
#     func2()
#     print(time.time() - ctime)      # 1.0483405590057373

# 通过yield实现保存状态+切换,(自定义的切换,并不是遇到IO才切换,所以不能节约时间)
# 单纯的切换不但不能提高效率,反而会降低效率
# import time
#
#
# def func1():
#     for i in range(10000000):
#         i += 1
#         yield
#
#
# def func2():
#     g = func1()
#     for i in range(10000000):
#         i += 1
#         next(g)
#
#
# if __name__ == '__main__':
#     ctime = time.time()
#     # func1()
#     func2()
#     print(time.time() - ctime)          # 2.008742094039917

# 优点:
# (1)协程的切换开销更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级
# (2)单线程内就可以实现并发的效果,最大限度地利用cpu
# 缺点:
# (1)协程的本质是单线程下,无法利用多核,可以是一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程
# (2)协程指的是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程
# 总结协程特点:
# (1)必须在只有一个单线程里实现并发
# (2)修改共享数据不需加锁
# (3)用户程序里自己保存多个控制流的上下文栈(需要保存状态)
# 附加:一个协程遇到IO操作自动切换到其它协程(如何实现检测IO,yield、greenlet都无法实现,就用到了gevent模块(select机制))
'''

# 虚拟环境
'''
# 1、解决不同项目依赖的模块版本不同的问题
# 2、pycharm中创建项目时选择
#     -基于系统解释器当前状态或纯净状态来创建虚拟环境
#     -这个虚拟环境是否可以给其他项目使用
# 3、装模块:
#       -cmd窗口下:pip3 install ...
#       -推荐用pycharm:setting
#       -pycharm下的terminal下装(相当于cmd)
# 4、环境变量的作用
#       -把一个路径加入到环境变量,以后该路径下的命令,可以在任意位置执行
'''

# greenlet模块
'''
# 初级模块,遇到IO不会切换;基于greenlet有了gevent模块,处理IO切换
import time
from greenlet import greenlet


def taskA():
    print('A one')
    # time.sleep(1)
    b.switch()
    print('A two')
    b.switch()


def taskB():
    print('B one')
    a.switch()
    print('B two')


if __name__ == '__main__':
    a = greenlet(taskA)
    b = greenlet(taskB)
    a.switch()
'''

# gevent模块
'''
# 基于greenlet写的,遇到IO自动切换
import time
import gevent


def taskA(name):
    print(f'A one {name}')
    gevent.sleep(1)             # IO操作 自动切换
    print(f'A two {name}')


def taskB(name):
    print(f'B one {name}')
    gevent.sleep(2)
    print(f'B two {name}')


if __name__ == '__main__':
    ctime = time.time()
    a = gevent.spawn(taskA, 'lh')
    b = gevent.spawn(taskB, 'lh')
    a.join()
    b.join()
    print(time.time() - ctime)      # 2.053565263748169
    # ctime = time.time()
    # taskA('lh')
    # taskB('lh')
    # a.join()
    # b.join()
    # print(time.time() - ctime)      # 3.0617334842681885


# 猴子补丁
import time
import gevent
from gevent import monkey
monkey.patch_all()      # 全部补丁


def taskA(name):
    print(f'A one {name}')
    time.sleep(1)             # 被猴子补丁替换后,gevent.sleep(1)
    print(f'A two {name}')


def taskB(name):
    print(f'B one {name}')
    time.sleep(2)           # gevent.sleep(2)
    print(f'B two {name}')


if __name__ == '__main__':
    ctime = time.time()
    a = gevent.spawn(taskA, 'lh')
    b = gevent.spawn(taskB, 'lh')
    a.join()
    b.join()
    print(time.time() - ctime)          # 2.0102903842926025
'''

# asyncio模块
'''
# 官方支持协程的库
import asyncio
import time

# @asyncio.coroutine          # python3.5以前的使用方法
# def task():
#     print('begin...')
#     yield from asyncio.sleep(1)            # asyncio.sleep(1) 模拟IO
#     print('end...')
#
#
# # print(task())       # <generator object task at 0x000001E7CB27BF90> (生成器)
# loop = asyncio.get_event_loop()         # 创建一个事件循环对象
# t = [task(), task()]            # 协程函数加括号,并不会真正执行,它需要提交给loop,让loop循环着执行
# ctime = time.time()
# loop.run_until_complete(asyncio.wait(t))
# loop.close()
# print(time.time() - ctime)


# python3.5之后的方法
async def task():
    print('begin...')
    await asyncio.sleep(1)
    print('end...')


# print(task())           # <coroutine object task at 0x000001A3D464F0C0>
loop = asyncio.get_event_loop()
t = [task(), task()]
ctime = time.time()
loop.run_until_complete(asyncio.wait(t))
loop.close()
print(time.time() - ctime)
'''


# IO模型
# http://liuqingzheng.top/python/Python%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/25-IO%E6%A8%A1%E5%9E%8B/
1 内存分为内核缓冲区和用户缓冲区(网络下载的资源,硬盘加载的资源,先放到内核缓冲区----》copy到应用程序的缓冲区,应用程序才能用这个数据)

2 io模型:
    -阻塞io(BIO)
    -非阻塞io(NIO)
    -io多路复用()  select(windows支持,windows不支持epoll,官方不提供redis的window版本),poll,epoll(linux支持)
    -异步io:
    -信号驱动io(理论,不在考虑范围内)

 

posted @ 2020-08-31 20:35  板鸭没有腿  阅读(75)  评论(0)    收藏  举报