在Twisted中使用线程

1 以线程安全模式运行代码  Twisted中大部分代码都不是线程安全例如protocol向transport写
入数据就不是线程安全因此我们需要种思路方法来在主事件循环中进行调度者可以使用
twisted.ernet.erfaces.IReactorThreads.callFromThread 来实现:


 
  1. from twisted.ernet import reactor
  2. def notThreadSafe(x):
  3.   """做些非线程安全事情"""
  4.   # ...
  5. def threadSafeScheduler:
  6.   """以线程安全方式运行"""
  7.   reactor.callFromThread(notThreadSafe,3) #将会运行notThreadSafe(3)在主时间循环中  Note

译者注
  callFromThread 意指从线程这个思路方法是供线程并且使其指定加入到主事件循环中执行比如worker线
程可以此思路方法将提交结果加入到主事件循环中这样就可以确保多线程运行worker而有可以使用线程安全方
式提交结果
  2 在线程中运行代码  有时我们希望在线程中运行代码比如阻塞存取APITwisted提供了这样做思路方
法在 IReactorThread API 中附加工具在包 twisted.ernet.threads 中提供这些思路方法允许我们把任务排队以
后在线程池中运行
  例如在线程中运行个我们可以:

 
 
  1. from twisted.ernet import reactor
  2. def aSillyBlockingMethod(x):
  3.   import time
  4.   time.sleep(2)
  5.   pr x
  6. # 在线程中运行
  7. reactor.callInThread(aSillyBlockingMethod,"2 secodns have passed")
 译者注
  callInThread 意指在线程中运行该思路方法需要在主事件循环中而执行其传入则是在线程中可以和上节
提供 callFromThread`结合使用即在worker线程中 `callFromThread 提交结果
  3 工具  工具作为 twisted.ernet.reactor 部分API提供但是并不是在 twisted.ernet.threads 中实现
  如果我们有多个思路方法需要在线程中以队列方式运行我们可以做:
 
  1. from twisted.internet import threads
  2. def aSillyBlockingMethodOne(x):
  3.   import time
  4.   time.sleep(2)
  5.   print x
  6. def aSillyBlockingMethodTwo(x):
  7.   print x
  8. # 排队线程运行两个
  9. commands=[(aSillyBlockingMethodOne,["calling first"])]
  10. commands.append((aSillyBlockingMethodTwo,["and the second"],{}))
  11. threads.callMultipleInThread(commands)
 
 
如果们希望得函数运行结果,那么们以使Deferred:

 
  1. from twisted.internet import threads
  2. def doLongCalculation():
  3.   # ... do long calculation here ...
  4.   return 3
  5. def printResult(x):
  6.   print x
  7. # 线程运行,并且通过 defer.Deferred 获结果
  8. d=threads.deferToThread(doLongCalculation)
  9. d.addCallback(printResult)

 
如果希望reactor线程调个,并且获结果,以使 blockingCallFromThread
 
  1. from twisted.internet import threads,reactor,defer
  2. from twisted.web.client import getPage
  3. from twisted.web.error import Error
  4. def inThread():
  5.   try:
  6.     result=threads.blockingCallFromThread(reactor,getPage,"http://twistedmatrix.com/")
  7.   except Error,exc:
  8.     print exc
  9.   else:
  10.     print result
  11.   reactor.callFromThread(reactor.stop)
  12. reactor.callInThread(inThread)
  13. reactor.run()
blockingCallFromThread 返回象或抛出异常,或通过抛出传递给函数。如果传递给函数返回个Deferred,返回Deferred回调值或抛出异常errback。
  4 管理线程池
  线程池 twisted.python.threadpool.ThreadPool 实现。
  们以修改线程池,增加或减少线程数量,以这么做:


 
  1. from twisted.internet import reactor
  2. reactor.suggestThreadPoolSize(30)

缺省线程池依赖于使reactor,缺省reactor使最5个,最10个。改变线程池尺寸,确保理解线程们资源使方式。
  Twisted2.5.0使线程
  刚才翻译应版本8.0.0Twisted线程指南,但还2.5.0,所以这里只记录8.0.0差异,不做重新翻译。
  当开始使线程,确保启动程序时候使如:

 
  1. from twisted.python import threadable
  2. threadable.init()
 

这回让Twisted以线程安全方式始化,不过仍然注意,Twisted部分仍然不线程安全。
  以线程安全方式运行代码始化两行:


 
  1. from twisted.python import threadable
  2. threadable.init(1)

2.5.0文档没有 blockingCallFromThread 例子。许根本就没有这个。
  实际载文档版本2.4.0,不过应该2.5.0样。
 
 
 
 
 
 
 
 
 
 
另外:

twisted里是通过回调机制来实现类似于多线程,意思是防止程序的运行由于等待某项任务的完成而陷入阻塞停滞,提高整体运行的效率。

from twisted.internet import reactor

1. reactor.callFromThread

Method callFromThread:

Cause a function to be executed by the reactor thread.

Use this method when you want to run a function in the reactor's thread from another thread. Calling callFromThread should wake up the main thread (where reactor.run() is executing) and run the given callable in that thread.

If you're writing a multi-threaded application the callable may need to be thread safe, but this method doesn't require it as such. If you want to call a function in the next mainloop iteration, but you're in the same thread, use callLater with a delay of 0.

此方法是本身是mainloop的线程,用reactor.stop()可以终止它。也可以reactor.callFromThread(reactor.stop)来终止它。但是这个方法会阻塞到主循环。

复制代码
#coding=utf-8
from twisted.internet import reactor
import time
def tt(i,j):
while1:
print i,'---------------',j
time.sleep(
1)

reactor.callFromThread(tt,
1,1)
reactor.callFromThread(tt,
4,2)
reactor.run()
复制代码

上面代码运行的结果是无限的打印1-------------------1,这个说明了主循环被阻塞住。

2. reactor.callInThread

Method callInThread:

Run the callable object in a separate thread.

此方法是创建独立的线程,用reactor stop方法无法停止它。这里涉及到一个线程池的概念

reactor.suggestThreadPoolSize(15)来设置线程池的大小,默认是最小是5,最大是10.如果在默认情况下

3. from twisted.internet import threads

threads.deferToThread(function),和callInThread一样,区别只是 deferToThread 可以返回一个deferred对象,从而允许你设定回调函数。

posted on 2012-05-23 17:37  很多不懂呀。。  阅读(2203)  评论(1编辑  收藏  举报

导航