昨日回顾
1 线程池和进程池的shutdown
- 等待池中所有任务执行完毕后关闭池(不能写在for 循环中)
2 定时器
- Timer:延迟几秒后执行一个任务,Timer( 时间,任务)
3 协程介绍
- 单线程下实现并发,认为制造出来的,操作系统感知不到,通过保存状态和切换,理想效果是遇到io切换
- 串行执行和通过yield 关键字切换,时间长短,单纯的切换反而影响效率
4 greenlet模块( 初级模块)
- 单纯的切换,遇到io不会切,g. switch( )
5 gevent模块
- monkey. patch_all( ) 猴子补丁,替换
- g1= gevent. spwan( 任务)
- g2= gevent. spwan( 任务)
- g1. join( )
- gevent. joinall( [ g1, g2] )
7 io模型
- 用户态,内核态
- 阻塞io,bio
- NIO – 非阻塞
- I/ O多路复用:目前最流行的模型,你所听到的所谓高并发的框架基本都是这个模型,ngixn,redis
- select(1024 个文件描述符)windows支持, poll(没有大小限制) ,都是再轮询
- epoll:没有大小限制,回调机制,windows不支持
- java的NIO和咱们说的NIO(非阻塞)不是一个东西,它就是io多路复用,New IO,Netty
- 异步I/ O模型
今日内容
1 基于协程的高并发服务端
2 并发编程大串讲
3 面向对象大串讲
1 基于协程的高并发服务端
from gevent import monkey, spawn; monkey. patch_all( )
from socket import socket
def make_server ( ip, port) :
server = socket( )
server. bind( ( ip, port) )
server. listen( 5 )
while True :
conn, addr = server. accept( )
spawn( task, conn)
def task ( conn) :
while True :
try :
data = conn. recv( 1024 )
if len ( data) == 0 : break
print ( data)
conn. send( data. upper( ) )
except Exception as e:
print ( e)
break
conn. close( )
if __name__ == '__main__' :
g= spawn( make_server, '127.0.0.1' , 8080 )
g. join( )
from socket import socket
from threading import Thread, current_thread
def task ( ) :
cli = socket( )
cli. connect( ( '127.0.0.1' , 8080 ) )
while True :
ss= '%s say hello' % current_thread( ) . name
cli. send( ss. encode( 'utf-8' ) )
data = cli. recv( 1024 )
print ( data)
for i in range ( 5000 ) :
t= Thread( target= task)
t. start( )
2 并发编程大串讲
操作系统发展史(了解)
多道技术(了解)
进程调度(了解)
- 进程状态:就绪,执行,阻塞
进程三状态(就绪,阻塞,运行)
同步异步 阻塞非阻塞:异步+ 非阻塞
- 同步是任务提交了,等待执行完成
- 异步是任务提交了,不等待执行完成,我自己去干自己的事,任务完成有回调
- 阻塞:程序运行的状态阻塞(io操作)
- 非阻塞:程序一直在运行的状态
创建进程的两种方式( 重点)
- 资源分配的最小单位
- 两种方式
- windows下开进程,在main函数下
进程join方法
- 等待子进程执行完成,父进程再继续执行
进程间数据相互隔离
- 因为开启一个进程,其实本身就是拉起一个python解释器,把进程跑在里面
僵尸进程与孤儿进程
- 进程死了,还有数据每回收
- 父进程死了,子进程就是孤儿进程
进程对象及其他方法
- 进程id 号,父进程id 号,关闭进程,查看进程是否存活
守护进程
- 主进程结束,守护进程跟着结束
互斥锁
- Lock
- 获得锁
- 释放锁
队列介绍
- 进程Queue
- 放值,取值
- 放满了,取没了(阻塞,报错)
IPC机制
- 进程间通信(队列机制)
GIL与普通互斥锁的区别
- 全局解释器锁,垃圾回收线程,不是数据安全的,线程必须拿到GIL锁,才能执行
- GIL不能保证我们自己的数据安全,自己的数据安全需要自己处理锁
- io密集型:线程
- 计算密集型:进程
多线程与多进程比较
- 进程是资源分配的最小单位
- cpu执行(调度)的最小单位
- 每个进程里至少有一条线程
死锁现象
- A这把锁,连续获得,第二次获得,就会夯住,形成死锁
- A线程已经获取A锁,等待去获取B锁,但是B锁被B线程获得,B线程在等待A锁
递归锁(可重入锁)
- 同一条线程,可以重复获得这把锁,每获得一次数字加一,只有计数为0 ,其他线程才能获得
- 解决死锁现象的第二种:A和B是同一把锁
信号量
- 运行多条线程同时修改数据
Event事件
- 发一个信号event. set ( ) ,原来在等待的(event. wait( ) )线程会继续执行
线程q
- 三种,先进先出,先进后出,优先级(越小)
池的概念
- 用来做缓冲,不会一次性创建出很多(进程,链接),池子多大,最多就创建多少
线程池
- 类不一样,用法完全一样
from concurrent. futures import ThreadPoolExecutor, ProcessPoolExecutor
pool= ThreadPoolExecutor( 5 )
pool. submit( 任务) . add_done_callback( 函数)
协程基本原理
- 单线程下实现并发,程序员制造出来的,切换+ 保存状态
gevent模块
协程实现tcp并发
io模型介绍
阻塞io模型
非阻塞io模型理论
io多路复用
asyncio模块
io模型
3 面向对象大串讲
类与对象
- class Person ( ) :
- p= Person( )
属性查找
- p. name: 先找对象自己,找不到去类中找,再找不到报错
类属性和对象属性
- 分别再不同的名称空间
对象的绑定方法
- 特殊之处,对象来调用,会自动传值,把对象自己传过来,当那个对象来调用,self就是谁
- 类也可以来调用,类调用就是普通函数,有几个参数就要传几个参数
函数和方法
-
类与数据类型( 类即类型)
-
类的继承(python支持多继承)
继承后属性查找顺序
派生(子类中新定义的属性或方法)
super ( ) 特殊的对象
多继承下的super ( FatBossGril. __mro__)
组合( 属性的值是指向另外一个类的对象)
多态与多态性
- 多态指的是一类事物有多种形态
- 多态性:一种调用方式,不同的执行效果
封装,隐藏属性
property
类方法,对象方法,静态方法
isinstance 和issubclass
isinstance 与type
反射getattr ,setattr ,hasattr ,delattr
__setattr__和__delattr__和__getattr__
- 添加/ 修改属性会触发它的执行
- 删除属性的时候会触发
- 只有在使用点调用属性且属性不存在的时候才会触发
- 递归现象:object . __setattr__( self, 'storage' , {
} ) (没讲)
__setitem__和__getitem和__delitem__(没讲)
__init__和__new__(不讲了)
其他魔法方法(不讲了)
元类(不讲了)
- type :所有类的类,但是继承object
- object :所有类的父类,同时由type 生成
一切皆对象之函数对象