为了练习并发编程,我编写了以下(次优)程序,该程序反复计算比用户输入的值大的第一个素数:
import Control.Concurrent
import Control.Concurrent.Chan
import Control.Monad (forever)
primeAtLeast n = -- Some pure code that looks up the first prime at least as big as n
outputPrimeAtLeast n = putStrLn $ show $ (n, primeAtLeast n)
main = do
chan <- newChan
worker <- forkIO $ forever $ readChan chan >>= outputPrimeAtLeast
forever $ (readLn :: (IO Int)) >>= (writeChan chan)
killThread worker
我想在后台有一个工作线程来完成实际的计算并(n, primeAtLeast n)
在完成后立即输出。
现在正在做什么:输入数字后n
,它会立即输出(n,
,将控件返回到主线程,primeAtLeast n
在后台计算并在primeAtLeast n)
完成后立即输出后一半。
那putStrLn
不是原子的吗?还是问题出在哪里?
试试这个:
outputPrimeAtLeast n = let p = primeAtLeast n in p `seq` putStrLn $ show (n, p)
以上强制在putStrLn
运行之前计算素数。
此外,您可以使用print
代替putStrLn . show
:
outputPrimeAtLeast n = let p = primeAtLeast n in p `seq` print (n, p)
或者,您可以使用一个putStrLn
函数,在开始打印任何内容之前强制每个字符。
strictPutStrLn :: Show a => a -> IO ()
strictPutStrLn x = let str = show x in str `listSeq` putStrLn str
listSeq :: [a] -> b -> b
listSeq [] w = w
listSeq (x:xs) w = x `seq` listSeq xs w
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句