• 线程、协成、IO模型


    1、线程就是CPU调度的最小单位。

    2、 # 线程进程之间的对比

            # 线程不能独立存在,必须在一个进程里
    # 线程的开启 关闭以及切换的开销要远远小于进程
    import time
    from threading import Thread
    from multiprocessing import Process
    def func(i):
        i += 1
    if __name__ == '__main__':
        start_time = time.time()
        t_l = []
        for i in range(50):
            t = Thread(target=func, args=(i,))
            t.start()
            t_l.append(t)
        for t in t_l:
            t.join()
        print('主线程')
        print(time.time() - start_time)
    if __name__ == '__main__':
        start_time = time.time()
        p_l = []
        for i in range(50):
            p = Process(target=func, args=(i,))
            p.start()
            p_l.append(t)
        for p in t_l:
            p.join()
        print('主进程')
        print(time.time() - start_time)

     

    3、    # 同一个进程之间的多个线程之间数据共享
    # 全局解释器锁GIL
    # 使得一个进程中的多个线程不能充分的利用多核
         # 这个锁能保证同一时刻只有一个线程运行

    4、
    # 主线程如果结束了 那么整个进程就结束
    # 守护线程 会等待主线程结束之后才结束.
    # 主进程 等待 守护进程 子进程
    # 守护进程 只守护主进程的代码就可以了
    # 守护线程不行 主线程如果结束了 那么整个进程就结束 所有的线程就都结束
    import time
    from threading import Thread
    def thread1():
        while True:
            print(True)
            time.sleep(0.5)
    
    def thread2():
        print('in t2 start')
        time.sleep(3)
        print('in t2 end')
    
    if __name__ == '__main__':
        t1 = Thread(target=thread1)
        t1.setDaemon(True)
        t1.start()
        t2 = Thread(target=thread2)
        t2.start()
        time.sleep(1)
        print('主线程')
    # 线程池
    # concurrent.futures.ThreadPoolExecutor
    # 线程池对象.map(func,iterable)
    # 线程池对象.submit 异步提交
    # 线程池对象.shutdown ==>close+join
    # 任务对象.result
    # 任务对象.add_done_callback 回调函数都是在子线程执行
    # 进程池
    # concurrent.futures.ProcessPoolExecutor
    # 任务对象.add_done_callback 回调函数都是在主进程执行
    # 协程
    # 在一个线程内的多个任务之间能够互相切换
    # 这个切换不是操作系统级别的 都是用户控制的
    # 最简单的切换以及状态的保留使用python原生的语法yield其实就可以实现
    # 但是一般情况下我们都是用gevent来完成协程的工作
    # 它能够帮助我们规避IO操作
    # 它内部使用的协程机制是greenlet
    # 协程比起线程的好处
    # 充分的利用了一条线程来提高CPU的工作效率
    # 不存在数据不安全的问题
    # join() 在主线程中没有其他阻塞事件的时候就是用join来保证协程任务都能顺利的执行完
    # spawn() 发起一个协程任务

    IO 模型

    # IO多路复用 - 操作系统提供的
    # 1.程序不能干预过程
    # 2.操作系统之间的差异
    import select
    import socket

    sk = socket.socket()
    sk.bind(('127.0.0.1',9090))
    sk.listen()
    sk.setblocking(False)
    rlst = [sk]
    while True:
    rl,wl,xl = select.select(rlst,[],[]) #[sk,conn1,conn2]
    # 为什么突然把sk返回回来了? sk对象有数据可以被读了
    # 为什么返回三个列表? 读事件的列表 写事件的列表 条件的列表
    # 为什么是列表? 有可能同时有多个被监听的对象发生读时间
    for obj in rl:
    if obj is sk: # is的意思更精准,判断的是obj就是sk
    conn,addr = obj.accept()
    rlst.append(conn)
    else:
    try:
    ret = obj.recv(1024)
    print(ret)
    obj.send(b'hello')
    except ConnectionResetError:
    obj.close()
    rlst.remove(obj)

    # TCP协议来说,如果对方关闭了连接
    # 另一方有可能继续 接收 空消息 或者 报错

    # 背代码
    # 将具体的情况套到代码中 将逻辑理顺
    # 理解之前IO多路复用的那张图

    # 什么叫IO多路复用
    # io多路复用是操作系统提供的一种 监听 网络IO操作的机制
    # 监听三个列表
    # 当某一个列表有对应的事件发生的时候
    # 操作系统通知应用程序
    # 操作系统根据返回的内容做具体的操作
    # 对于只有一个对象需要监听的情况 IO多路复用并无法发挥作用
    # 对于并发接收网络请求的应用场景 IO多路复用可以帮助你在节省CPU利用率和操作系统调用的基础上完成并发需求

    # IO多路复用
    # select 是windows上的机制 轮询的方式来监听每一个对象是否有对应的事件发生的,数据越多延迟越大
    # 能够处理的对象数是有限的
    # poll linux 和select的机制基本一致,对底层存储被监听对象的数据结构做了优化
    # 能够处理的对象个数增加了
    # epoll linux 采用了回调函数的方式来通知应用被监听的对象有事件发生了
  • 相关阅读:
    md基本语法
    CodeBlocks安装使用、汉化以及更改配色
    hexo+github搭建个人博客教程和各种坑记录
    GB/T 38637.1-2020 物联网 感知控制设备接入 第1部分:总体要求
    山东大学909数据结构与程序设计考研经验分享
    GB/T 39083-2020 快递服务支付信息交换规范
    GB/T 38829-2020 IPTV媒体交付系统技术要求 内容接入
    GB/T 37733.3-2020 传感器网络 个人健康状态远程监测 第3部分:终端技术要求
    GB/T 38801-2020 内容分发网络技术要求 互联应用场景
    GB/T 30269.809-2020 信息技术 传感器网络 第809部分:测试:基于IP的无线传感器网络网络层协议一致性测试
  • 原文地址:https://www.cnblogs.com/zhaosijia/p/9391922.html
Copyright © 2020-2023  润新知