快速业务通道

使用GPars解决常见并发问题 - 编程入门网

作者 佚名技术 来源 NET编程 浏览 发布时间 2012-06-13
tweets

并行处理

如果 清单 1中的程序静候等待,它也可能不止等待一个处理。如果我将每个远程请求放入一个后台线程中,程序会并行等待每个响应查询,如图 2 所示:

图 2. 并行读取 tweets

使用GPars解决常见并发问题(3)

时间:2012-03-17 IBM Alex Miller

GPars Executors DSL 使得我们更容易将 清单 1中的程序从串行处理转换为并行处理,如清单 2 所示:

清单 2. 并行读取 tweets (langTweetsParallel.groovy)

import twitter4j.Twitter   import twitter4j.Query   import groovyx.gpars.GParsExecutorsPool   @Grab(group=''net.homeip.yusuke'', module=''twitter4j'', version=''2.0.10'')   @Grab(group=''org.codehaus.gpars'', module=''gpars'', version=''0.10'')   def recentTweets(api, queryStr) {   query = new Query(queryStr)   query.rpp = 5  // tweets to return   query.lang = "en"  // language   tweets = api.search(query).tweets   threadName = Thread.currentThread().name   tweets.collect {    "[${threadName}-${queryStr}] @${it.fromUser}: ${it.text}" } }   def api = new Twitter()   GParsExecutorsPool.withPool {   def retrieveTweets = { query ->    tweets = recentTweets(api, query)    tweets.each {     println "${it}" } }   [''#erlang'',''#scala'',''#clojure''].each {    retrieveTweets.callAsync(it) }   }

我使用 Executors DSL 为 GParsExecutorsPool添加了一段 import语句,并使用 Groovy Grape 依赖性系统添加了一段 Grab语句来捕获 GPars 库。然后我引入了一个 GParsExecutorsPool.withPool块,这将增强块中的代码以添加额外功能。在 Groovy 中,可以使用 call方法来调用闭包。GParsExecutorsPool将在底层内存池中作为任务执行通过 call 方法调用的闭包。此外,GParsExecutorsPool通过一个 callAsync方法增强闭包,被调用后该方法在无阻塞的情况下立即返回。在本例中,我包装了我的 tweet 搜索并将操作包装到一个闭包中,然后为每个查询异步调用它。

由于 GPars 将这些任务分配给了一批作业员,我现在可以并行执行我的所有搜索了(只要内存池足够大)。我也可以并行处理每个查询所得结果,在其到达时打印到屏幕。

该例展示了后台处理能够提高性能和响应能力的两种方式:I/O 等待并行完成,依赖于该 I/O 的处理也并行发生。

Executors

您可能想知道什么是 executor,GParsExecutorsPool中的后台处理如何工作。Executor实际上是 Java 5 中引入的 java.util.concurrent库的一部分。java.util.concurrent.Executor接口仅有一个方法:execute(Runnable)。它存在的目的在于将任务的提交与一个 Executor实现中任务的实际执行方式分离开来。

java.util.concurrent.Executors类提供许多有用的方法来创建各种不同的线程池类型支持的 Executor实例。GParsExecutorsPool默认使用一个含守护进程线程和固定数目线程的一个线程池(Runtime.getRuntime().availableProcessors() + 1)。当默认设置不合适时,要更改线程池大小、使用一个自定义 ThreadFactory或指定现有的整个 Executor池(withExistingPool)很简单。

要更改线程数,我可以将 GParsExecutorsPool线程计数传递给 withPool方法,如清单 3 所示:

清单 3. 使用线程计数启动一个 Executor 池

GParsExecutorsPool.withPool(8) {   // ...   }

或者如果我想传递一个具有专门命名线程的自定义线程工厂,我可以像清单 4 这样做。

清单 4. 使用自定义线程工厂启动一个 Executor

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号