单线程下实现IO切换
1、Greenlet
greenlet可以实现两个任务之间的来回切换,但遇到IO会阻塞,不会切(使用这个模块之前需要在电脑命令提示符中输入 pip3 install greenlet 进行安装)
例如:
from greenlet import greenlet
import time def eat(name):
print('%s eat 1' %name)
time.sleep(30) #遇到IO不会切
g2.switch('alex')
print('%s eat 2' %name)
g2.switch()
def play(name):
print('%s play 1' %name)
g1.switch()
print('%s play 2' %name) g1=greenlet(eat)
g2=greenlet(play) g1.switch('egon')
打印结果:
egon eat 1
alex play 1
egon eat 2
alex play 2
2、gevent
先在命令提示符中输入 pip3 install gevent 进行安装
Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,它遇到IO阻塞时会自动切换任务。
#用法
g1=gevent.spawn(func,1,,2,3,x=4,y=5)创建一个协程对象g1,spawn括号内第一个参数是函数名,如eat,后面可以有多个参数,
可以是位置实参或关键字实参,都是传给函数eat的
g2=gevent.spawn(func2)
g1.join() #等待g1结束
g2.join() #等待g2结束
#或者上述两步合作一步:gevent.joinall([g1,g2])
g1.value#拿到func1的返回值
import gevent def eat(name):
print('%s eat 1' %name)
gevent.sleep(5)
print('%s eat 2' %name)
def play(name):
print('%s play 1' %name)
gevent.sleep(3)
print('%s play 2' %name) g1=gevent.spawn(eat,'egon')
g2=gevent.spawn(play,'alex') # gevent.sleep(100)
# g1.join()
# g2.join()
gevent.joinall([g1,g2]) 打印结果:
egon eat 1
alex play 1
alex play 2
egon eat 2
上例gevent.sleep(2)模拟的是gevent可以识别的io阻塞,
而time.sleep(2)或其他的阻塞,gevent是不能直接识别的需要用下面一行代码,打补丁,就可以识别了
from gevent import monkey;monkey.patch_all()必须放到被打补丁者的前面,如time,socket模块之前
或者我们干脆记忆成:要用gevent,需要将from gevent import monkey;monkey.patch_all()放到文件的开头
monkey.patch_all(),相当于把这个程序里只要涉及到IO操作的都打了一个标记,这样可以识别time模块下的IO行为。
from gevent import monkey;monkey.patch_all()
import gevent
import time def eat(name):
print('%s eat 1' %name)
time.sleep(5)
print('%s eat 2' %name)
def play(name):
print('%s play 1' %name)
time.sleep(3)
print('%s play 2' %name) g1=gevent.spawn(eat,'egon')
g2=gevent.spawn(play,'alex') # gevent.sleep(100)
# g1.join() 保证主线程不死掉
# g2.join()
gevent.joinall([g1,g2]) 运行结果和上面程序的结果相同
使用current_thread 可以看线程名
from gevent import monkey;monkey.patch_all()
from threading import current_thread
import gevent
import time def eat():
print('%s eat 1' %current_thread().name)
time.sleep(5)
print('%s eat 2' %current_thread().name)
def play():
print('%s play 1' %current_thread().name)
time.sleep(3)
print('%s play 2' %current_thread().name) g1=gevent.spawn(eat)
g2=gevent.spawn(play) # gevent.sleep(100)
# g1.join()
# g2.join()
print(current_thread().name)
gevent.joinall([g1,g2]) 打印结果:
MainThread
DummyThread-1 eat 1
DummyThread-2 play 1
DummyThread-2 play 2
DummyThread-1 eat 2
注:DummyThread-1,和DummyThread-2是两个假线程,干活的其实都还是主线程在干,没有开过新的线程
spawn提交任务的方式是异步提交,提交完之后不会等在原地,再接着提交下一个任务
学完gevent模块后,可以这样实现并发:
1、开多个进程,用上了多核优势
2、每个进程里再开线程,提高了并发数
3、每个线程使用gevent模块方式实现遇到IO切,把单个线程的效率提到最高
这样做极大的提升了程序的效率
单线程下实现IO切换的更多相关文章
- 异步、+回调机制、线程queue、线程Event、协程、单线程实现遇到IO切换
# from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor # import requests # import o ...
- gevent监测单线程下的io进行切换
from gevent import monkey;monkey.patch_all() import gevent import time def eat(name): print('%s eat ...
- Centos下的IO监控与分析
近期要在公司内部做个Linux IO方面的培训, 整理下手头的资料给大家分享下 各种IO监视工具在Linux IO 体系结构中的位置 源自 Linux Performance and Tuni ...
- Linux下的IO监控与分析
Linux下的IO监控与分析 近期要在公司内部做个Linux IO方面的培训, 整理下手头的资料给大家分享下 各种IO监视工具在Linux IO 体系结构中的位置 源自 Linux Performan ...
- 【转载】Linux下的IO监控与分析
近期要在公司内部做个Linux IO方面的培训, 整理下手头的资料给大家分享下 各种IO监视工具在Linux IO 体系结构中的位置 源自 Linux Performance and Tuning G ...
- 生产者和消费者模型producer and consumer(单线程下实现高并发)
#1.生产者和消费者模型producer and consumer modelimport timedef producer(): ret = [] for i in range(2): time.s ...
- Linux下的IO监控与分析(转)
各种IO监视工具在Linux IO 体系结构中的位置 源自 Linux Performance and Tuning Guidelines.pdf 1 系统级IO监控 iostat iostat -x ...
- Winform下实现图片切换特效的方法
本文实例讲述了Winform下实现图片切换特效的方法,是应用程序开发中非常实用的一个功能.分享给大家供大家参考之用.具体方法如下: 本实例源自网络,功能较为齐全.丰富!主要功能代码如下: using ...
- Python开发【笔记】:单线程下执行多个定时任务
单线程多定时任务 前言:公司业务需求,实例当中大量需要启动定时器的操作:大家都知道python中的定时器用的是threading.Timer,每当启动一个定时器时,程序内部起了一个线程,定时器触发执行 ...
随机推荐
- 看完这篇 Session、Cookie、Token,和面试官扯皮就没问题了
Cookie 和 Session HTTP 协议是一种无状态协议,即每次服务端接收到客户端的请求时,都是一个全新的请求,服务器并不知道客户端的历史请求记录:Session 和 Cookie 的主要目的 ...
- Python学习-第五节:面向对象
概念: 核心是“过程”二字,“过程”指的是解决问题的步骤,即先干什么再干什么......,基于面向过程设计程序就好比在设计一条流水线,是一种机械式的思维方式.若程序一开始是要着手解决一个大的问题,面向 ...
- Java并发基础04. 线程技术之死锁问题
我们知道,使用 synchronized 关键字可以有效的解决线程同步问题,但是如果不恰当的使用 synchronized 关键字的话也会出问题,即我们所说的死锁.死锁是这样一种情形:多个线程同时被阻 ...
- Ubuntu16.04默认Python3.5升级Python3.6踩坑
好久没更新博客了,每天还是踩坑中.今天遇到第一个问题“ImportError: No module named 'secrets'”,导包是常见问题.这次的问题导致我又重装了一次环境,不过这是一个新服 ...
- var、let和const的区别详解
let 和 const 是 ECMAScript6 新推出的特性,其中 let 是能够替代 var 的"标准",所以我们探讨 var.let 和 const 的区别,首先应该知 ...
- es elasticsearch 6/7 设置内存方法
es节点的默认的heap内存大小是 1G 大小,在实际生产中,很容易导致内存溢出而导致进程被kill掉.所以我们一般会自己配置自己的,2.x的版本可以通过export ES_HEAP_SIZE=10g ...
- flask-redirect
flask-redirect from flask import Flask, url_for, request, redirect app = Flask(__name__) @app.route( ...
- Tcl编成第二天,set与unset
代码如下: #!/usr/bin/tclsh set value "one" puts $value unset value puts $value set表示创建一个变量第一个参 ...
- C/C++ 数据精确度的设置
#include<iostream>#include<iomanip> //此库为代码最后一行快捷设置数据格式需要用的的库 #include<math.h>usin ...
- MySQL学习之路4-数据的导入导出
数据的导入 通过数据库管理工具,先建表,然后导入表记录. 通过sql语句导入: load data local infile '表路径' into table stuscore fields term ...