线程

一、线程

  1、什么是线程:

      线程也是一种多任务编程方法,可以利用计算机的多核资源完成程序的并发执行。线程被称为轻量级的进程。

  2、线程特征: 

     * 线程是计算机多核分配的最小单位
      * 一个进程可以包含多个线程
      * 线程也是一个运行的过程,也要消耗计算机资源,多个线程共享共用进程的资源和空间
      * 线程的创建删除消耗的资源都要远远小于进程
      * 多个线程之间独立运行互不干扰
      * 线程也有自己的特有属性,比如指令集,线程栈,ID,TID

  3、threading 模块创建线程

   1、threading.Thread()
        功能: 创建线程对象
        参数:name   线程名称 默认Thread-1
                 target 线程函数
                 args   元组 给线程函数位置传参
                 kwargs 字典 给线程函数键值传参
        返回:线程对象
    2、t.start()   启动线程 自动运行线程函数
     3、t.join([timeout])     回收线程

  4、线程对象属性

      t.is_alive()  查看线程状态
       t.name 线程名称
       t.setName()  设置线程名称
       t.getName()  获取线程名称
       threading.currentThread()  获取到当前线程对象

  5、t.daemon 属性

    默认情况下主线程结束退出不会影响分支线程执行,设置为True时 则分支线程随主线程退出
     1、设置 daemon值方法:
          t.daemon = True
          t.setDaemon(True)
     2、判断属性值:
          t.isDaemon()
         * 要在start前设置,不会和join同用

  6、创建自己的线程类

    步骤 :
       1 继承 Thread
       2 加载父类Thread中 __init__
       3 重写run方法

二、线程通信

  1、通信方法:多个线程共享进程空间,所以线程间通信使用全局变量完成(进程的全局变量对进程内线程均可见)
  2、注意事项:线程间使用全局变量进行通信,全局变量为共享资源,往往需要同步互斥机制保证通讯安全
  3、线程同步互斥方法
   4、线程的event

       1、创建事件对象:     
         e = threading.Event()
       2、事件阻塞函数:如果e为设置状态则不阻塞否则阻塞
         e.wait([timeout]) 
       3、设置事件:将e变为设置状态
         e.set()
       4、清除事件
         e.clear()
      详见示例:thread_event.py

三、线程锁  Lock

   lock = threading.Lock()   创建锁对象
    lock.acquire()  上锁
    lock.release()  解锁
    with  lock       上锁 (with方式上锁执行完代码块自动解锁)
   * 也可以通过with上锁,上锁状态调用acquire会阻塞。
   详见示例:thread_lock.py

四、python线程的GIL问题 (全局解释器锁)

  1、背景:
      python ---》支持多线程操作 ---》IO的同步和互斥 ---》加锁 ---》超级锁,给解释器加锁 ---》解释器同一时刻只解释一个线程,此时其他线程需要等待
  2、python线程的执行效率低的原因(后果):
      一个解释器,同一时刻只解释执行一个线程,此时其他线程需要等待。所以导致Python线程效率低下。但是当遇到IO阻塞时线程会主动让出解释器,因此Python线程更加适合高延迟IO程序开发。
  3、python  GIL问题解决方案
     * 尽量使用进程完成并发
     * 不使用cpython解释器,可以用 c#,java做解释器
     * 尽量使用多种方案组合的方式进行并发操作,python线程可以用在高延迟多阻塞的IO情形
     * 修改c解释器

五、效率测试

  分别测试 多进程  多线程  单进程执行相同的IO操作和CPU操作的时间
    Line cpu: 9.014907121658325
    Line IO:  4.548823118209839
    thread cpu: 9.38966417312622
    thread IO:   4.6143529415130615
    Process cpu: 5.466824531555176
    Process IO:  2.9468178749084473

要求 :

  1. 什么是线程 
       threading
         Thread()
         t.start()
         t.join()
         t.name  t.getName t.setName  t.daemon  t.is_alive()
   2. 自定义线程类  
       继承 Thread 
       重写 run
   3. 线程通信
      使用全局变量通信
      线程的同步互斥
   4. Python线程 GIL
        影响 : 同一时刻只能解释一个线程,造成python线         程效率低
        python线程 : 适用于高阻塞IO程序
***************************Day08*******************************

一、进程和线程的区别和联系

   1.两者都是多任务编程的方式,都能够使用计算机的多核资源
    2.进程的创建删除要比线程消耗更多的计算机资源
    3. 进程空间独立,数据相互不干扰,有专门的IPC,线程使用全局变量进行通信,更加简单
    4. 一个进程可以创建多个线程分支,两者之间存在包含关系
    5. 多个线程公用进程的空间资源,在资源操作时往往需要同步互斥
    6. 进程线程都独立执行,在系统中都有自己特有资源的属性,ID,代码段,栈区,命令集等资源

二、进程与线程的使用场景

   * 需要创建较多并发,同时任务关联性比较强时一般用多线程
    * 不同的任务模块可能更多使用进程
    * 使用进程线程需要考虑数据的处理复杂度,比如进程间通信是否方便,同步互斥是否过于复杂
    * 使用python考虑线程GIL问题

三、服务器模型

  1、硬件服务器 : 主机   集群
            厂商 : IBM  HP  联想  浪潮
   2、软件服务器 :编写的服务端应用程序,在硬件服务器上运行,一般依托硬于操作系统。给用户提供一套完整的服务
   3、服务器种类:
      webserver ---》 网络的后端应用服务器程序,提供数据处理和逻辑处理
      httpserver ---> 接受http请求,返回http响应
      邮箱服务器 ---》 处理邮件请求,进行邮件收发
      文件服务器 --》提供文件的上传下载存储
   4、功能实现:网络连接,逻辑处理,数据运算,数据交互,协议实现,网络数据传输。。。。
   5、模型结构: C/S   客户端服务器模型
                      B/S   浏览器服务器模型
   6、服务器目标:处理速度更快,数据安全性更强,并发量更高
      1、硬件 : 更高的配置,更好的集成分布技术,更高的网络优化和网络安全技术
      2、软件 : 占用更少的计算机资源,运行效率更稳定,算法更优良,安全性更好,并发性更高,更容易扩展,更合理的技术搭配

四、基础服务端模型

1、循环服务器模型:

       单进程程序,循环接收客户请求,处理请求。同一时刻只能处理一个请求,处理完毕再接受下一个请求。
       1、优点:实现简单,占用资源少
       2、缺点:无法同时处理多客户端任务,体验差
       3、适用情况:处理的任务可以短时间完成,不需要建立并发,更适合udp使用。(udp比tcp更适合循环)

2、并发服务器模型:

       能够同时处理多个客户端任务请求。
      1、IO 并发:  IO多路复用      (协程)      
           优点 : 可以实现IO的并发操作,速度快,占用系统资源少
           缺点 : 不能监控cpu密集型程序的情况,并能有长期阻塞
     2、多进程/多线程并发: 为每个客户端创建单独的提供一个进程/线程,处理客户端请求
           优点 : 每个客户端可以长期占有服务器运行程序,能够使用多核资源,可以处理IO或者cpu运算
           缺点 : 消耗系统资源高

3、多进程并发模型

      使用fork实现多进程并发
       1、创建套接字,绑定,监听
       2、等待接收客户端请求
       3、创建新的进程处理客户端请求
       4、原有进程继续等待接收新的客户端连接
       5、如果客户端退出则关闭子进程

      cookie:
        在父进程中忽略子进程状态改变,子进程退出自动由系统处理
         signal.signal(signal.SIGCHLD,signal.SIG_IGN)
      详见示例:fork_server.py

五、ftp 文件服务器项目

  1、项目功能:
     * 服务端和客户端两部分,要求启动一个服务端,可以同时处理多个客服端请求,每个客户端可能回连续发送命令
     * 功能包含:1、可以查看服务器文件库中所有的普通文件(查看的文件列表)
                      2、从客户端可以下载文件库的文件到本地
                      3、可以将本地文件上传的服务端文件库
                      4、退出
     * 客户端使用print在终端打印简单的页面命令提示,通过命令提示发起请求
   2、技术分析:
        1. tcp套接字更适合文件传输
        2. 并发方案  ---》 fork 多进程并发
        3. 每个功能都要求单独封装,整体功能写在一个类中
        4. 如何搭建整体架构,完成网络通讯
        5. 对文件的读写操作
        6. 获取文件列表 ----》 os.listdir() ,粘包的处理
   3、功能分析:
     1. 获取文件列表
         客户端:* 发送请求
                    * 得到回复判断能否获取列表
                    * 接收文件名称列表打印
         服务端:* 接收请求
                     * 判断请求类型
                     * 判断能否满足请求,回复信息确认
                     * 执行请求发送文件列表
     2、文件下载
        客户端:* 发送请求 (文件名)
                   * 得到回复判断能否下载
                   * 下载文件
        服务端:* 接收请求
                   * 判断请求类型
                   * 判断能否满足请求,回复信息确认
                   * 执行请求发送文件
   4、cookie:
      os.listdir(puth)  获取目录中文件列表  puth路径
       os.path.isfile()  判断是否为普通文件
       os.path.isdir()   判断是否为目录(文件夹)
要求:
    1、进程线程的区别和联系
    2、进程间通信方式都知道哪些,有什么特点
    3、同步互斥意义是什么,什么情况下用
    4、给一个情形,分析下用线程还是用线程,理由
    5、一些常见概念挖掘:僵尸进程,进程状态,GIL

总结:
   1. 进程线程的区别和联系
     * 都是多任务编程
     * 一个进程包含多个线程
     * 都是动态的占有资源的,线程共享进程的资源
     * 进程比线程消耗资源更多
     * 进程空间独立使用特定的IPC,线程使用全局变量
   2. 服务器模型  
     循环模型 : 同一时刻只能处理一个请求
     并发模型 : IO 并发 : 多个IO任务
                 多进程/多线程并发 : 任何任务
   3. 基于fork的多进程并发程序
      每当有一个客户端连接就创建一个新的进程
   4. ftp文件服务程序

****************************Day09********************************

一、多线程并发

1、threading的多线程并发

   1、对比多进程并发:
       *优势: 消耗资源较少
       *缺点: 线程应该更注意共享资源的操作
       * 在Python中应该注意GIL问题,网络延迟较高,线程并发也是一种可行的办法
     2、实现步骤:
       1、创建套接字,绑定,监听
       2、接收客户端连接请求,创建新的线程
       3、主线程继续等待接收其他客户端连接
       4、分支线程执行对应的函数处理客户端具体请求
       5、处理完客户端请求后分支线程自然退出,关闭客户端套接字(当客户端断开,则分支线程结束)
     3、cookie:
       import traceback
      traceback.print_exc()
         功能:更详细的打印异常信息

二、集成模块的使用

   python2 SocketServer
    python3 socketserver
    功能:通过模块的不同类的组合完成多进程/多线程的tcp/udp的并发程序
      StreamRequestHandler     处理tcp套接字请求
      DatagramRequestHandler  处理udp套接字请求
      TCPServer  创建tcp server
      UDPServer  创建udp server
      ForkingMixIn    创建多进程
      ForkingTCPServer -->  ForkingMixIn + TCPServer
      ForkingUDPServer -->  ForkingMixIn + UDPServer
      ThreadingMixIn  创建多线程
      ThreadingTCPServer –>   ThreadingMixIn + TCPServer
      ThreadingUDPServer -->  ThreadingMixIn + UDPServer

三、HTTPServer V2.0

1、基于多线程并发的HTTPServer

    1. 接收(客户端)浏览器http请求
     2. 解析客户端请求
     3. 根据解析结果返回对应内容
     4. 如果没有请求内容则返回404
     5. 组织数据,形成HTTP Response格式进行回发给客户端

2、升级

    1. 采用多线程并发接收多个客户端请求
     2. 基本的请求解析,根据请求返回相应的内容
     3. 除了可以请求静态网页,也可以请求简单的数据
     4. 将功能封装在一个类中   

3、技术点:

    1、socket   tcp 套接字
     2、http协议的请求响应格式
     3、线程并发的创建方法(threading并发)
     4、类的基本使用

4、协程基础:

  1、定义:纤程,微线程。协程的本质是一个单线程程序,所以协程不能够使用计算机多核资源。
   2、作用:能够高效的完成并发任务, 占用较少的资源。因此协程的并发量较高
   3、原理:通过记录应用层的上下文栈区,实现在运行中进行上下文跳转,达到可以选择性的运行想要运行的部分,以提高程序的运行效率。
   4、优点:消耗资源少
            无需切换开销
            无需同步互斥
            IO并发性好
   5、缺点:无法利用计算机多核
   6、yiled ---》 协程实现的基本关键字
   7、第三方库:
      1、greenlet
          greenlet.greenlet()  生成协程对象
          gr.switch()   选择要执行的协程事件
      2、gevent
             1、将协程事件封装为函数
             2、生成协程对象
          gevent.spawn(func,argv)
           功能:生成协程对象
           参数:func 协程函数
                    argv 给协程函数传参
           返回值:返回协程对象
       3、回收协程
         gevent.joinall()
          功能:回收协程
          参数:列表 将要回收的协程放入列表
         gevent.sleep(n)
          功能:设置协程阻塞,让协程跳转
          参数:n 阻塞时间
       4、from gevent import monkey
         monkey.patch_all()
          功能:修改套接字的IO阻塞行为
         * 必须在socket导入之前使用(导入)

posted on 2018-10-12 16:25  破天荒的谎言、谈敷衍  阅读(213)  评论(0)    收藏  举报

导航