我写了以下概念证明代码:
import time
from multiprocessing.pool import ThreadPool
class Maybe:
def __init__(self):
self._value = None
self._exists = False
def exists(self):
return self._exists
def value(self):
if not self.exists():
raise ValueError("Maybe doesn't hold any value")
return self._value
def set(self, value):
self._value = value
self._exists = True
def unset(self):
self._value = None
self._exists = False
class Future(object):
def __init__(self):
self._holder = Maybe()
self._handler = None
def _set(self, value):
self._holder.set(value)
self._invoke()
def _invoke(self):
if self._handler and self._holder.exists():
self._handler(self._holder.value())
def then(self, handler):
self._handler = handler
self._invoke()
def fib(count):
f,s = 0,1
for i in xrange(count):
f,s =s,f+s
return s
pool = ThreadPool(5)
def test(fun, arg):
def print_fib(x):
print("fib => {0}, {1}\n".format(arg, len(str(x))))
tb = time.time()
future = Future()
future.then(print_fib)
future._async_result = pool.apply_async(fun, [arg], callback=future._set)
ta = time.time()
print ("Time elapsed : {0}".format(ta - tb))
return future
x1=test(fib, 2029)
x2=test(fib, 989999)
x3=test(fib, 103)
x4=test(fib, 38484)
x5=test(fib, 20)
time.sleep(3)
我期待所有调用以异步方式运行。但它们似乎不是异步运行的。例如,带有103
参数的调用预计在以989999
为参数的调用之前完成。我没有看到这种情况发生。如果我使用更大的参数进行第二次调用,即使第一次调用也需要更多时间。
有人可以解释发生了什么吗?为什么它们不能异步运行?
答案 0 :(得分:1)
线程是连续运行的。但是fib
跑得太快了;因此很难判断它们是否同时运行。 (fib(989999)
除外)
请尝试以下操作(我将已用时间打印部件移至print_fib
以正确打印已用时间。):
def test(fun, arg):
def print_fib(x):
print("fib => {0}, {1}\n".format(arg, len(str(x))))
ta = time.time()
print ("Time elapsed : {0}".format(ta - tb))
tb = time.time()
future = Future()
future.then(print_fib)
future._async_result = pool.apply_async(fun, [arg], callback=future._set)
return future
x1 = test(time.sleep, 2)
x2 = test(time.sleep, 5)
x3 = test(time.sleep, 1)
x4 = test(time.sleep, 4)
x5 = test(time.sleep, 3)
#time.sleep(10)
x1._async_result.get()
x2._async_result.get()
x3._async_result.get()
x4._async_result.get()
x5._async_result.get()
输出:
fib => 1, 4
Time elapsed : 1.00200009346
fib => 2, 4
Time elapsed : 2.00099992752
fib => 3, 4
Time elapsed : 3.00200009346
fib => 4, 4
Time elapsed : 4.00200009346
fib => 5, 4
Time elapsed : 5.00200009346
答案 1 :(得分:1)
问题是ThreadPool
将所有线程设置为守护进程,即如果主线程退出所有线程将终止。 time.sleep(3)
不足以让您的流程完成其任务,这就是原因。请注意,您的“已用时间”日志不正确,因为它会测量触发线程所需的时间,而不是实际任务。
您应始终.join
个帖子。使用ThreadPool
,您可以使用以下代码执行此操作:
...
x1=test(fib, 2029)
x2=test(fib, 989999)
x3=test(fib, 103)
x4=test(fib, 38484)
x5=test(fib, 20)
pool.close()
pool.join()
同时将所有日志移至print_fib
函数,它应该按预期工作。