并发编程之基于协程的高并发服务端、面向对象回顾等相关内容-41
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 基于协程的高并发服务端
# server.py
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) # 这里还需要join吗?不能加,我们不希望它夯在这
def task(conn):
while True:
# bytes.upper()
# str.upper()
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__':
# make_server('127.0.0.1',8080)
g=spawn(make_server,'127.0.0.1',8080)
g.join()
# client.py
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:先找对象自己,找不到去类中找,再找不到报错
类属性和对象属性
-分别再不同的名称空间
# class Person:
# name='lqz'
#
# p=Person()
# p.name='egon' # 只是改了对象自己名称空间中的name,不会影响到类的name
# print(p.name)
#
# p1=Person()
# print(p1.name)
# # 就想改类中的name,如何改
# Person.name='xxx'
# print(p1.name) # xxx
#
# print(p.name) # egon
对象的绑定方法
-特殊之处,对象来调用,会自动传值,把对象自己传过来,当那个对象来调用,self就是谁
-类也可以来调用,类调用就是普通函数,有几个参数就要传几个参数
# class Person:
# name = 'lqz'
#
# def play(self):
# print(self.name)
#
# # 特殊之处,对象来调用,会自动传值,把对象自己传过来,当那个对象来调用,self就是谁
#
# p=Person()
# p.play()
# p.name='egon'
# p.play()
# 类也可以来调用,类调用就是普通函数,有几个参数就要传几个参数
# Person.play([1,2]) # 普通函数,怎么传值都行
函数和方法
# from types import FunctionType, MethodType
#
# class Person:
# name = 'lqz'
#
# def play(self):
# print(self.name)
#
# print(isinstance(Person.play, FunctionType)) # 类来调用,play就是个普通函数,打印出True
# print(isinstance(Person.play, MethodType)) # 不是方法,打印出false
# p=Person()
# print(isinstance(p.play, FunctionType)) # False
# print(isinstance(p.play, MethodType)) # True
类与数据类型(类即类型)
# class Person:
# # name = 'lqz'
# # l=[1,2,3]
# # dic={'name':'lqz'}
# # p=Person()
# # print(type(l))
# # print(type(p))
类的继承(python支持多继承)
# class Human:
# name = 'lqz'
#
# def test(self):
# print('test')
#
#
# class Person(Human):
# name = 'egon'
#
#
# # print(Person.name)
# ## 查找顺序
# p = Person()
# print(p.name)
# 对象自己找,类里找,父类找,父类。。(mro列表)
继承后属性查找顺序
派生(子类中新定义的属性或方法)
super()特殊的对象
# class Human:
# name = 'lqz'
# def test(self):
# print('test')
# class Animal:
# def test222(self):
# print('test2222')
# class Person(Human,Animal):
# name='egon'
# def test(self):
# super().test() # super代指Human的对象
# super().test222() # super代指Animal的对象
# #特殊对象,很特殊,代指父类对象,但是分情况代之的不一定(mro列表)是哪个父类
多继承下的super(FatBossGril.__mro__)
组合(属性的值是指向另外一个类的对象)
# class Human:
# name = 'lqz'
#
# def __init__(self, name):
# self.name = name
#
#
# class Animal:
# pass
#
#