首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >这个程序产生了多少线程(geturls9.hs)

这个程序产生了多少线程(geturls9.hs)
EN

Stack Overflow用户
提问于 2016-08-07 08:53:41
回答 1查看 79关注 0票数 2

我正在读Haskell中的并行并行编程的第11章。在这本书中,以下程序用于并发获取URL:

代码语言:javascript
运行
复制
main = do
  xs <- foldr conc (return []) (map getURL sites)
  print (map B.length xs)
 where
  conc ioa ioas = do
    (a,as) <- concurrently ioa ioas
    return (a:as)

假设"get“作业是[g0, g1, g2]。据我所知,xs将绑定到以下结构:

代码语言:javascript
运行
复制
g0 `conc` (g1 `conc` (g2 `conc` (return [])))

现在,我的问题是在本例中将创建多少个线程。我的猜测是,将创建7个线程(与我期望用于此任务的4个线程相反):

代码语言:javascript
运行
复制
 thread0: g0 `conc` (g1 `conc` (g2 `conc` (return [])))
   thread1: g0
   thread2: (g1 `conc` (g2 `conc` (return [])))
     thread3: g1
     thread4: (g2 `conc` (return []))
       thread5: g2
       thread6: return []

这个推理正确吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-08-07 20:00:32

所有的猜测都是错误的!实际上,有六个线程生成了

把大锤拿出来-

代码语言:javascript
运行
复制
import Control.Concurrent.Async
import Control.Concurrent (myThreadId)

import qualified Data.ByteString as B

-----------------------------------------------------------------------------

sites = ["http://www.google.com",
         "http://www.wikipedia.com/wiki/Spade",
         "http://www.wikipedia.com/wiki/Shovel"]

getURL _ = return B.empty

annotate :: IO a -> IO a
annotate action = do
    tid <- myThreadId
    putStrLn $ "I'm a thread and my ID is: " ++ show tid
    action

-- <<main
main = do
  xs <- foldr conc (return []) (map getURL sites)
  print (map B.length xs)
 where
  conc ioa ioas = do
    (a,as) <- concurrently (annotate ioa) (annotate ioas)
    return (a:as)
-- >>

传递给concurrently的所有操作都将使用annotate包装,这将导致线程将其ThreadId阻塞为stdout。我得到了-

+$ ./geturls9 9我是一个线程,我的ID是: ThreadId 5,我是一个线程,我的ID是: ThreadId 6,我是一个线程,我的ID是: ThreadId 8,我是一个线程,我的ID是: ThreadId 9,我是一个线程,我的ID是: ThreadId 10,我是一个线程,我的ID是: ThreadId 7,0,0,0,0

当然,由于GHC版本和赛车的不同,您对同一程序的结果几乎肯定会在ID号和订单的细节上有所不同。

所以,你的直觉很好!您的分析只需要一个,因为整个表达式g0 `conc` (g1 `conc` (g2 `conc` (return [])))本身并没有传递给concurrently,所以您的thread0当然只是主线程,而不是由异步库创建的线程。

请注意,异步为并发处理任何mapConcurrently提供了Traversable,因此不必使用foldr构建自己的foldr。为什么在Haskell的并行和并发编程中没有提到这个函数,我不确定。它是在异步-2.0.1.0中引入的,Haskell平台版本2012.4.0.0 ( PCPH介绍中提到了所有测试代码)都包含异步-2.0.1.3。这可能是教学上的原因,也许是发布中常见的延迟,再加上代码是针对旧版本的平台/库开发的,谁知道呢。该介绍还提到,“随着平台新版本的发布,样例代码将被更新。”如果你有强烈的感觉,提交一个雷特姆

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38812494

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档