目录

1. 进程池与线程池

2. 协程

3. gevent

4. 单线程下实现并发的套接字通信

首先写一个基于多线程的套接字

服务端:

from socket import *

from threading import Thread

def comunicate(conn):

while True: # 通信循环

try:

data = conn.recv(1024)

if len(data) == 0: break

conn.send(data.upper())

except ConnectionResetError:

break

conn.close()

def server(ip, port, backlog=5):

server = socket(AF_INET, SOCK_STREAM)

server.bind((ip, port))

server.listen(backlog)

while True: # 链接循环

conn, client_addr = server.accept()

print(client_addr)

# 通信

t=Thread(target=comunicate,args=(conn,))

t.start()

if __name__ == '__main__':

s=Thread(target=server,args=('127.0.0.1',8081))

s.start()

每连接上一个客户端便会创造一个线程 , 那么如果有一万个客户端的话服务端会产生一万个线程 , 然后服务端就炸了 , 所以要想个办法限制连接个数 , 即限制

1. 进程池\线程池

开启一个进程池 , 会开启一定个数的进程 , 然后将任务提交给进程就可以了

1 介绍

concurrent.futures模块提供了高度封装的异步调用接口

ThreadPoolExecutor:线程池,提供异步调用

ProcessPoolExecutor: 进程池,提供异步调用

Both implement the same interface, which is defined by the abstract Executor class.

2 基本方法

submit(fn, *args, **kwargs)

异步提交任务

map(func, *iterables, timeout=None, chunksize=1)

取代for循环submit的操作

shutdown(wait=True)

相当于进程池的pool.close()+pool.join()操作

wait=True,等待池内所有任务执行完毕回收完资源后才继续

wait=False,立即返回,并不会等待池内的任务执行完毕

但不管wait参数为何值,整个程序都会等到所有任务执行完毕

submit和map必须在shutdown之前

result(timeout=None)

取得结果

add_done_callback(fn)

回调函数

导入模块

from concurrent.futures import ProcessPoolExecutor

创建一个进程池

p=ProcessPoolExecutor(4)#进程数为4

提交任务, 有两种方式

a.同步调用:同步调用:提交完一个任务之后,就在原地等待,等待任务完完整整地运行完毕拿到结果后,再执行下一行代码,会导致任务是串行执行的

res=p.submit(function,参数一...).result()

b. 异步调用:提交完一个任务之后,不在原地等待,而是直接执行下一行代码,会导致任务是并发执行的,,结果futrue对象会在任务运行完毕后自动传给回调函数

res=p.submit(function,参数一...)

回调函数(用于异步调用)

每提交一个任务 , 会产生一个对象 , 给这个任务绑定了一个函数 , 这个函数会在你提交的任务完成后自动触发 , 且会将这个对象当作参数传给这个函数

这个函数用于处理子进程运行完之后产生的结果

多进程下的回调函数

from concurrent.futures import ProcessPoolExecutor

import time,os

import requests

def get(url):

print('%s GET %s' %(os.getpid(),url))

time.sleep(3)#处理的太快看不出效果 , 模拟多处理3秒

response=requests.get(url)#爬取网站内容

if response.status_code == 200:

res=response.text

else:

res='下载失败'

return res#返回爬取数据

# 到这里任务运行完了之后自动调用parse函数 ,

# 回调函数 , 处理任务的结果用

def parse(future):

time.sleep(1)

res=future.result()#future对象下的result为任务的返回值

print('%s 解析结果为%s' %(os.getpid(),len(res)))

if __name__ == '__main__':

urls=[

'https://www.baidu.com',

'https://www.sina.com.cn',

'https://www.tmall.com',

'https://www.jd.com',

'https://www.python.org',

'https://www.openstack.org',

'https://www.baidu.com',

'https://www.baidu.com',

'https://www.baidu.com',

]

#开启进程数为9的进程池

p=ProcessPoolExecutor(9)

start=time.time()

for url in urls:

# 异步调用:提交完一个任务之后,不在原地等待,而是直接执行下一行代码,会导致任务是并发执行的,,结果futrue对象会在任务运行完毕后自动传给回调函数

future=p.submit(get,url)

#将parse设为回调函数

future.add_done_callback(parse) #parse会在任务运行完毕后自动触发,然后接收一个参数future对象

p.shutdown(wait=True)

print('主',time.time()-start)

print('主',os.getpid())

多线程与多进程相同,只需将p=ProcessPoolExecutor(9)改为p=ThreadPoolExecutor(9)就可以了

2. 单线程下实现并发-------协程

目标:

在单线程下实现并发,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。

并发(多个任务看起来是同时执行就是并发):切换+保存状态

协程:

协程是单线程实现并发

注意:协程是程序员意淫出来的东西,操作系统里只有进程和线程的概念(操作系统调度的是线程)

在单线程下实现多个任务间遇到IO就切换就可以降低单线程的IO时间,从而最大限度地提升单线程的效率

强调

python的线程属于内核级别的,即由操作系统控制调度(如单线程遇到io或执行时间过长就会被迫交出cpu执行权限,切换其他线程运行)

单线程内开启协程,一旦遇到io,就会从应用程序级别(而非操作系统)控制切换,以此来提升效率(!!!非io操作的切换与效率无关)

对比操作系统控制线程的切换,用户在单线程内控制协程的切换

优点如下

协程的切换开销更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级

单线程内就可以实现并发的效果,最大限度地利用cpu

缺点如下

协程的本质是单线程下,无法利用多核,可以是一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程

协程指的是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程

总结

必须在只有一个单线程里实现并发

修改共享数据不需加锁

用户程序里自己保存多个控制流的上下文栈

附加:一个协程遇到IO操作自动切换到其它协程(如何实现检测IO,yield、greenlet都无法实现,就用到了gevent模块(select机制))

3. gevent

他是一个第三方的库 , 可以实现在单线程内遇到 IO 任务自动切换

geven是不能直接识别的 需要在整个文件最前面加上一行代码

from gevent import monkey;monkey.patch_all()

步骤 :

打补丁

导入from gevent import spawn

定义有 IO 操作的任务(函数)

将多个任务分别提交给协程

g1=spawn(函数名,函数的参数)

g2=spawn(函数名,函数的参数)

等待两个协程运行完 ,

g1.join()

g2.join()

:因为这里是异步调用 , 主线程代码运行完了 , 主线程就会死掉 , 协程里面的任务也不会运行完 就跟着死了, 所以要加上join方法 ,如果主线程要运行很久 , 或者是一个死循环 , 就不用加join方法 ,即上面的的第五步就可以忽略

from gevent import monkey;monkey.patch_all()

from gevent import spawn,joinall #pip3 install gevent

import time

def play(name):

print('%s play 1' %name)

time.sleep(5)

print('%s play 2' %name)

def eat(name):

print('%s eat 1' %name)

time.sleep(3)

print('%s eat 2' %name)

start=time.time()

g1=spawn(play,'王昭锦')

g2=spawn(eat,'王昭锦')

g1.join()

g2.join()

# joinall([g1,g2]) #上面两步可以并成这一步

print('主',time.time()-start)

运行结果如下:

'''

王昭锦 play 1

王昭锦 eat 1

王昭锦 eat 2

王昭锦 play 2

主 5.009259223937988

'''

4. 单线程下实现并发的套接字通信

服务端:

from gevent import monkey;monkey.patch_all()

from socket import *

from gevent import spawn

def comunicate(conn):

while True: # 通信循环

try:

data = conn.recv(1024)

if len(data) == 0: break

conn.send(data.upper())

except ConnectionResetError:

break

conn.close()

def server(ip, port, backlog=5):

server = socket(AF_INET, SOCK_STREAM)

server.bind((ip, port))

server.listen(backlog)

while True: # 链接循环

conn, client_addr = server.accept()

print(client_addr)

# 通信

spawn(comunicate,conn)

if __name__ == '__main__':

g1=spawn(server,'127.0.0.1',8080)

g1.join()

python 协程池gevent.pool_进程池\线程池,协程,gevent相关推荐

  1. Python进阶(5)_进程与线程之协程、I/O模型

    三.协程 3.1协程概念 协程:又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存 ...

  2. 进程 线程 协程_进程,线程,协程那些事

    无论我们写出怎样的程序,最后都是由操作系统来运行我们的程序,而操作系统如何管理我们的程序,我们程序的数据如何保存和计算,这些都是操作系统需要处理的事情,我们只要将写好的程序交给操作系统就好. 虽然操作 ...

  3. 进程、线程、协程和管程的区别

    大家都知道,计算机是为了模拟现实世界,其中计算机领域最伟大的发明之一就是操作系统.操作系统对于计算机来说是其核心的存在,可以说操作系统的地位就像计算机的灵魂一样.操作系统的诞生是为了运行用户程序,事实 ...

  4. python是如何实现进程池和线程池的_进程、线程、线程池和协程如何理解?

    1.进程.线程.线程池的概念 进程是一个动态的过程,是一个活动的实体.简单来说,一个应用程序的运行就可以被看做是一个进程,而线程,是运行中的实际的任务执行者.可以说,进程中包含了多个可以同时运行的线程 ...

  5. 怎么更进一步学python_【百尺竿头,更进一步学Python】Python进阶课程——进程,线程和协程的区别...

    本文带来各类奇怪的IT百科知识. [百尺竿头,更进一步学Python]Python进阶课程--进程:线程和协程的区别 现在多进程多线程已经是老生常谈了:协程也在最近几年流行起来.今天我们本文主要介绍进 ...

  6. python 协程、进程、线程_Python 中的进程、线程、协程

    1. 进程 进程是正在运行的程序实例,是内核分配资源的最基本的单元.进程拥有自己独立的堆和栈,独立的地址空间,资源句柄.进程由 OS 调度,调度开销较大,在并发的切换过程效率较低. Python 提供 ...

  7. python提高——进程、线程、协程对比及代码实现

    目录 1多任务 1.1并发 1.2并行 2线程 2.1引入线程 2.2线程进行顺序 2.3线程封装 2.4多线程-共享全局变量 2.5资源竞争 2.6互斥锁 2.7死锁 3进程 3.1进程创建 3.2 ...

  8. python进程线程协程区别_进程和线程、协程的区别

    现在多进程多线程已经是老生常谈了,协程也在最近几年流行起来.python中有协程库gevent,py web框架tornado中也用了gevent封装好的协程.本文主要介绍进程.线程和协程三者之间的区 ...

  9. python线程协程进程的区别_进程和线程、协程的区别

    现在多进程多线程已经是老生常谈了,协程也在最近几年流行起来.python中有协程库gevent,py web框架tornado中也用了gevent封装好的协程.本文主要介绍进程.线程和协程三者之间的区 ...

  10. Python 进程、线程、协程

    进程.线程.协程 一.线程 1. 进程和线程 线程:计算机中可以被cpu调度的最小单元(真正在工作). 进程:计算机资源分配的最小单元(进程为线程提供资源). #如容器,资源隔离使用的进程级别隔离.一 ...

最新文章

  1. 吸水间最低动水位标高_水库水位库容监测系统方案
  2. 命名实体识别学习笔记——使用Ltp
  3. IDEA 新特性:提前知道代码怎么走
  4. NR 5G UE初始接入流程
  5. 成功解决ValueError: row index was 65536, not allowed by .xls format
  6. BERT源码分析(PART II)
  7. android 随机布尔值,在 Android 的某些机型,v1.2.2 v1.2.1 加密会导致 boolean 类型的值丢失的问题...
  8. html5离线储存不足,html5的离线存储问题
  9. C++学习之路 | PTA(甲级)—— 1099 Build A Binary Search Tree (30分)(带注释)(精简)
  10. 深入学习webpack(四)
  11. 电脑cpu和手机cpu的差距有多大?
  12. Selenium2Library(RF)浏览器打不开问题汇总
  13. Android 开发环境搭建之——ADT-Bundle for Windows
  14. 洪恩在线c语言测试,洪恩软件之编程之道C/C++程序设计入门视频教程
  15. 计算机桌面word不见怎么办,电脑桌面word 电脑桌面上word不见了怎么办
  16. IOS应用在iPhone5和iPhone5s上不能全屏显示,应用画面上下各有1条黑色的解决方案
  17. Instant类[java]
  18. vmbox主机和虚拟机无法共通网络服务 主机无法使用虚拟机的网络服务 虚拟机无法使用主机的网络服务
  19. qq邮件如何设置html阅读,使用qq邮箱发送html格式的邮件
  20. 计算机启动 滴的一声,电脑开机时滴的一声是为什么?

热门文章

  1. selenium禁止弹窗_python:使用带有selenium的firefox时禁用下载弹出窗口
  2. web版本 开源压测工具_siege--Web性能压测工具
  3. 二叉树的创建_大多数人都不会手写创建并遍历二叉树,一航这里帮你终结了
  4. http status 404 – 未找到_从零开始搭建自己的网站004添加404处理页面
  5. ubuntu修改用户名、计算机名、主目录名
  6. S3C2440与SDRAM的地址连线分析
  7. VirtualCopy()操作I/O口 物理地址为什么要移8位
  8. esp8266 micropython oled_micropython(4):使用ESP8266 控制 oled 屏幕,并显示 helloworld 字符...
  9. float32精度_PyTorch 1.6来了:新增自动混合精度训练、Windows版开发维护权移交微软...
  10. 初学者怎样看懂python代码_入门编程(初学者怎样看懂代码)