进程池线程池与单程下实现并发

一、 socket并发(进程线程池铺垫)

 

 服务端:

import socket
from threading import Thread
"""
服务端:
1.固定的ip和port
2.24小时不间断提供服务
3.支持高并发
"""
server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(5) # 半连接池


def communicate(conn):
while True:
try:
data = conn.recv(1024) # 阻塞
if len(data) == 0:break
print(data)
conn.send(data.upper())
except ConnectionResetError:
break
conn.close()

while True:
conn,addr = server.accept() # 阻塞
print(addr)
t = Thread(target=communicate,args=(conn,))
t.start()
View Code

 

 客户端:

import socket


client = socket.socket()
client.connect(('127.0.0.1',8080))

while True:
    info = input('>>>:').encode('utf-8')
    if len(info) == 0:continue
    client.send(info)
    data = client.recv(1024)
    print(data)
View Code

 

 

二 、 进程池线程池

 

如一中的socket并发,假如客户端的数量呈万级甚至百万千万级时,此时cup恐怕要冒烟了,那怎么样能解决同一时间的超大高并发呢?进程池和线程池能够解决

说在前面:无论是开线程还是开进程其实都消耗资源,开线程消耗的资源比开进程的小。

 

池:

    为了减缓计算机硬件的压力,避免计算机硬件设备崩溃

    虽然减轻了计算机硬件的压力,但是一定程度上降低了持续的效率

 

进程池线程池:

    为了限制开设的进程数和线程数,从而保证计算机硬件的安全

 

from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
import time
import os

 

# 示例化池对象
# 不知道参数的情况,默认是当前计算机cpu个数乘以5,也可以指定线程个数
pool = ProcessPoolExecutor(5) # 创建了一个池子,池子里面有20个线程


def task(n):
print(n,os.getpid())
time.sleep(2)
return n**2


def call_back(n):
print('我拿到了结果:%s'%n.result())
"""
提交任务的方式
同步:提交任务之后,原地等待任务的返回结果,再继续执行下一步代码
异步:提交任务之后,不等待任务的返回结果(通过回调函数拿到返回结果并处理),直接执行下一步操作
"""


# 回调函数:异步提交之后一旦任务有返回结果,自动交给另外一个去执行
if __name__ == '__main__':
# pool.submit(task,1)
t_list = []
for i in range(20):
future = pool.submit(task,i).add_done_callback(call_back) # 异步提交任务
t_list.append(future)

# pool.shutdown() # 关闭池子并且等待池子中所有的任务运行完毕
# for p in t_list:
# print('>>>:',p.result())
print('')
View Code

 

 

三 、 协程

 

学习协程前的铺垫:

进程:资源单位(车间)

线程:最小执行单位,即CPU的执行单位(流水线)

协程:单线程下实现并发

 

并发:看上去像同时执行的就可以称之为并发。

 

多道技术:

    空间上的复用

    时间上的复用

核心:切换+保存状态

 

协程:完全就是高技术的人自己意淫出来的,但是没想到还挺好用

    通过代码层面自己检测 io 自己实现切换,让操作系统误以为你这个线程没有 io

    实现原理就是:通过代码实现切换+保存状态

    运用范围:单线程实现高并发

开多进程

多个进程下面再开多线程

多个线程下开协程

实现高并发

gevent 模块的使用(genvet就是用来实现类似切换+保存效果)

from gevent import monkey;monkey.patch_all() # 监测代码中所有io行为
from gevent import spawn
# gevent本身识别不了time.sleep等不属于该模块内的io操作
import time

def heng(name):
print('%s 哼'%name)
time.sleep(2)
print('%s 哼' % name)


def ha(name):
print('%s 哈'%name)
time.sleep(3)
print('%s 哈' % name)
start = time.time()
s1 = spawn(heng,'egon')
s2 = spawn(ha,'echo')

s1.join()
s2.join()
# heng('egon')
# ha('kevin')

print('',time.time()-start)
View Code

 

用 gevent 模块实现网络通信的单线程高并发

服务端

from gevent import monkey;monkey.patch_all()
from gevent import spawn
import socket


def communicate(conn):
    while True:
        try:
            data = conn.recv(1024)
            if len(data) == 0:break
            print(data.decode('utf-8'))
            conn.send(data.upper())
        except ConnectionResetError:
            break
    conn.close()


def server():
    server = socket.socket()
    server.bind(('127.0.0.1',8080))
    server.listen(5)
    while True:
        conn,addr = server.accept()
        spawn(communicate,conn)

if __name__ == '__main__':
    s1 = spawn(server)
    s1.join()
View Code

 

客户端

from threading import Thread,current_thread
import socket


def client():
    client = socket.socket()
    client.connect(('127.0.0.1',8080))
    n = 1
    while True:
        data = '%s %s'%(current_thread().name,n)
        n += 1
        client.send(data.encode('utf-8'))
        info = client.recv(1024)
        print(info)

if __name__ == '__main__':
    for i in range(500):
        t = Thread(target=client)
        t.start()
View Code

 

四 、IO模型初识

上海张江第一帅元少对于 IO 模块的理解:

https://www.cnblogs.com/Dominic-Ji/p/10806351.html

 

转载于:https://www.cnblogs.com/SlookUp/p/10839740.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值