案例3:非确定性的task函数
import gevent
import random
def task(pid):
"""
Some non-deterministic task
"""
gevent.sleep(random.randint(0, 2) * 0.001)
print('Task %s done' % pid)
def synchronous(): # 同步
for i in range(1, 10):
task(i)
def asynchronous(): # 异步
threads = [gevent.spawn(task, i) for i in range(10)]
gevent.joinall(threads)
print('Synchronous:')
synchronous()
print('Asynchronous:')
asynchronous()
'''
输出结果:
Synchronous:
Task 1 done
Task 2 done
Task 3 done
Task 4 done
Task 5 done
Task 6 done
Task 7 done
Task 8 done
Task 9 done
Asynchronous:
Task 0 done
Task 2 done
Task 4 done
Task 6 done
Task 8 done
Task 3 done
Task 9 done
Task 1 done
Task 5 done
Task 7 done
Process finished with exit code 0
'''
在同步的情况下,所有的任务都是顺序运行的,这会导致主程序在每个任务执行时阻塞(即暂停主程序的执行)。
该程序的重要部分是 gevent.spawn将给定函数包装在 Greenlet 线程中的部分。初始化的greenlets列表存储在数组中threads,该数组传递给gevent.joinall阻止当前程序运行所有给定greenlets的函数。只有当所有 greenlet 终止时,执行才会向前推进。
需要注意的重要事实是异步情况下的执行顺序基本上是随机的,并且异步情况下的总执行时间比同步情况少得多。事实上,同步案例完成的最长时间是每个任务暂停 0.002 秒导致整个队列暂停 0.02 秒。在异步情况下,最大运行时间大约为 0.002 秒,因为没有一个任务阻止其他任务的执行。
案例4:从服务器异步获取数据
import gevent.monkey
gevent.monkey.patch_socket()
import gevent
import urllib2
import simplejson as json
def fetch(pid):
response = urllib2.urlopen('http://json-time.appspot.com/time.json')
result = response.read()
json_result = json.loads(result)
datetime = json_result['datetime']
print('Process %s: %s' % (pid, datetime))
return json_result['datetime']
def synchronous():
for i in range(1,10):
fetch(i)
def asynchronous():
threads = []
for i in range(1,10):
threads.append(gevent.spawn(fetch, i))
gevent.joinall(threads)
print('Synchronous:')
synchronous()
print('Asynchronous:')
asynchronous()
在更常见的用例中,从服务器异步获取数据,fetch()请求之间的运行时会有所不同,具体取决于请求时远程服务器上的负载。