进程池线程池 协程 gvent 单线程实现并发套接字
1.基于多线程实现套接字服务端支持并发
服务端
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()
客户端
from socket import *
client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8081))
while True:
msg=input('>>: ').strip()
if len(msg) == 0:continue
client.send(msg.encode('utf-8'))
data=client.recv(1024)
print(data.decode('utf-8'))
2.进程池
使用进程池就是对启动进程数加以限制
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
import time,random,os
def task(name,n):
print('%s%s is running'%(name,os.getpid()))
time.sleep(random.randint(1,3))
return n
if __name__ == '__main__':
# print(os.cpu_count())#打印cpu核数
p=ProcessPoolExecutor(4)#进程池预留了4个进程,可以提供开启。后续一次性可以同时开启4个进程,进程号不会变。
# 如果不传参数(数字),那么默认最多开启的进程数为电脑的核数
l=[]
for i in range(20):
#同步提交
# res=p.submit(task,'进程pid:').result()
# print(res)
#异步提交
future=p.submit(task,'进程pid:',i)#submit是异步提交,直接传位置参数,或关键字参数
l.append(future)
p.shutdown(wait=True)#关闭进程池的入口,并且在原地等待进程池内所有任务运行完毕
for future in l:
print(future.result())
print('主')
不使用回调函数进行异步提交,自行解析
import time, os, random
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
from threading import Thread
import requests
def get(url):
print('%s GET %s' % (os.getpid(), url))
time.sleep(random.randint(1, 3))
response = requests.get(url)
if response.status_code == 200:
return response.text
else:
return '下载失败'
def parse(res):
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.bilibili.com',
'https://www.youku.com',
'https://www.baidu.com',
'https://www.baidu.com',
'https://www.baidu.com',
]
p = ProcessPoolExecutor(4)
l = []
for url in urls:
future = p.submit(get, url)
l.append(future)
p.shutdown(wait=True)
for future in l:
res = future.result()
parse(res)
print('主')
异步一般与回调函数连用
使用回调函数
import time, os, random
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
from threading import Thread
import requests
def get(url):
print('%s GET %s' % (os.getpid(), url))
time.sleep(random.randint(1, 3))
response = requests.get(url)
if response.status_code == 200:
return response.text
else:
return '下载失败'
def parse(res):
res=res.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.bilibili.com',
'https://www.youku.com',
'https://www.baidu.com',
'https://www.baidu.com',
'https://www.baidu.com',
]
p = ProcessPoolExecutor(4)
start=time.time()
for url in urls:
future = p.submit(get, url)
future.add_done_callback(parse)#parse会在任务完毕后触发,然后接收一个参数future对象
p.shutdown(wait=True)
print(time.time()-start)
print('主%s'%os.getpid())
使用线程池开多线程进行任务
线程池和进程池的用法很相似
import time, os, random
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
from threading import Thread,current_thread
import requests
def get(url):
print('%s GET %s' % (current_thread().name, url))
time.sleep(random.randint(1, 3))
response = requests.get(url)
if response.status_code == 200:
return response.text
else:
return '下载失败'
def parse(res):
res=res.result()
print('%s解析结果为%s' % (current_thread().name, 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.bilibili.com',
'https://www.youku.com',
'https://www.baidu.com',
'https://www.baidu.com',
'https://www.baidu.com',
]
p = ThreadPoolExecutor(4)
start=time.time()
for url in urls:
future = p.submit(get, url)
future.add_done_callback(parse)#parse会在任务完毕后触发,然后接收一个参数future对象
#如果开启的是进程,那么来干parse这件事的是主进程
#如果开启的是线程,那么线程池里的线程也可以来做parse,谁有空谁做
p.shutdown(wait=True)
print(time.time()-start)
print('主%s'%current_thread().name)
3.协程
使用协程的目标是想要在单线程下实现并发
实现协程的原理是:切换+保存状态
注意:协程是程序员意淫出来的东西,操作系统里只有进程和线程的概念。
在单线程下实现多个任务间遇到IO就切换可以降低单线程的IO时间,从而最大限度地提升单线程的效率。
不遇到IO就进行切换的话并不能提升单线程的效率,这样不算是成功的协程。
4.gevent
要实现单线程下的协程,需要gevent模块
from gevent import spawn,sleep
from gevent import monkey,joinall
monkey.patch_all()#这样gevent就能识别所有IO行为
import time
#gevent不能识别本身以外的IO行为,为了监听所有的IO行为,要导入monkey
def play(name):
print('%s play1'%name)
time.sleep(3)
print('%s play2'%name)
def eat(name):
print('%s eat1'%name)
time.sleep(5)
print('%s eat2'%name)
start=time.time()
g1=spawn(play,'刘清正')#这里是异步提交
g2=spawn(eat,'刘清正')
joinall([g1,g2])
stop=time.time()
print(stop-start)
5.单线程实现并发套接字
进程池线程池 协程 gvent 单线程实现并发套接字的更多相关文章
- python 进程、线程与协程的区别
进程.线程与协程区别总结 - 1.进程是计算器最小资源分配单位 - 2.线程是CPU调度的最小单位 - 3.进程切换需要的资源很最大,效率很低 - 4.线程切换需要的资源一般,效率一般(当然了在不考虑 ...
- 三、进程和线程、协程在python中的使用
三.进程和线程.协程在python中的使用 1.多进程一般使用multiprocessing库,来利用多核CPU,主要是用在CPU密集型的程序上,当然生产者消费者这种也可以使用.多进程的优势就是一个子 ...
- 图解Python 【第八篇】:网络编程-进程、线程和协程
本节内容一览图: 本章内容: 同步和异步 线程(线程锁.threading.Event.queue 队列.生产者消费者模型.自定义线程池) 进程(数据共享.进程池) 协程 一.同步和异步 你叫我去吃饭 ...
- python基础之进程、线程、协程篇
一.多任务(多线程) 多线程特点:(1)线程的并发是利用cpu上下文的切换(是并发,不是并行)(2)多线程执行的顺序是无序的(3)多线程共享全局变量(4)线程是继承在进程里的,没有进程就没有线程(5) ...
- python并发编程之进程、线程、协程的调度原理(六)
进程.线程和协程的调度和运行原理总结. 系列文章 python并发编程之threading线程(一) python并发编程之multiprocessing进程(二) python并发编程之asynci ...
- Python3 进程、线程和协程
Infi-chu: http://www.cnblogs.com/Infi-chu/ 进程.线程和协程的对比 1.定义对比 进程:是系统进行资源分配的基本单位,每启动一个进程,操作系统都需要为其分配运 ...
- 协程、gevent实现异步io、进程、线程、协程对比
异步io的说白了就是遇到io操作的时候,就停下来去做别的事情.io分网络io和磁盘io,网络io比如说打开一个网站获取数据,下载一首歌等等,磁盘io就是把数据存到一个文件里面,写到磁盘上. 从网站上获 ...
- Python进程、线程、协程及IO多路复用
详情戳击下方链接 Python之进程.线程.协程 python之IO多路复用
- 进程、线程、协程和GIL(二)
上一篇博客讲了进程.线程.协程和GIL的基本概念,这篇我们来说说在以下三点: 1> python中使用threading库来创建线程的两种方式 2> 使用Event对消来判断线程是否已启动 ...
随机推荐
- Doker学习笔记之一:安装
基于Ubuntu16.04LTS 第一步:通过脚本进行安装 $ curl -sSL https://get.docker.com/ | sh 或者选择国内的DaoCloud安装脚本 $ curl -s ...
- ES6 的模块系统
原文地址:https://hacks.mozilla.org/2015/08/es6-in-depth-modules/ ES6 是 ECMAScript 第 6 版本的简称,这是新一代的 JavaS ...
- Mac下利用safari调试 Cordova的WebApp
1.打开Safari,打开顶部菜单栏中的'偏好设置',切换'高级',将“在菜单栏中显示开发菜单”钩上: 2.打开iPhone的“设置”程序,进入“Safari”->“高级”页面开启“Web检查器 ...
- es7 class装饰器
文档http://es6.ruanyifeng.com/#docs/decorator ts文档 https://www.tslang.cn/docs/handbook/decorators.html ...
- Flask web开发之路十三
g对象 ### 保存全局变量的g属性:g:global1. g对象是专门用来保存用户的数据的.2. g对象在一次请求中的所有的代码的地方,都是可以使用的. 项目结构: g_demo.py文件代码: f ...
- Python与金融量化分析----金融与量化投资
一:金融了解 金融:就是对现有资源进行重新的整合之后,进行价值和利润的等效流通. 金融工具: 股票 期货 黄金 外汇 基金 ............. 股票: 股票是股份公司发给出资人多的一种凭证,股 ...
- mapper.xml
#{}如果是字符串就不用加引号,否则报错,${}也一样,不是占位符需要加
- zookeeper的Java客户端API
zookeeper作为一个分布式服务框架,主要用来解决分布式数据一致性问题,对多种语言提供了API.这里主要记录下JAVA客户端API的使用. 1.创建会话 客户端可以通过创建一个ZooKeeper实 ...
- 【每日一题】 UVA - 1588 Kickdown
题意:uva的题,每道都是有背景的orz,都是阅读理解 题解:暴力模拟,拿着短的那个串,对着长的一格一格往左滑,每滑一格暴力扫一遍.然后再从头往右滑,我这里wa了三发,wa了后习惯性瞎改,改到后来循环 ...
- hive中创建子表并插入数据过程初始化MR报错解决方法
本文继成上一篇通过hive分析nginx日志文章,详情参考下面链接: http://www.cnblogs.com/wcwen1990/p/7066230.html 接着来: 创建业务子表: drop ...