Haskell 部分同时生效的行动清单
我有一个表示shell命令的字符串列表,我希望一次并发执行10个。这是我在Haskell中第一次真正尝试并发编程,我遇到了一些麻烦 我的想法是将列表分为十个元素的子列表,然后Haskell 部分同时生效的行动清单,haskell,asynchronous,concurrency,Haskell,Asynchronous,Concurrency,我有一个表示shell命令的字符串列表,我希望一次并发执行10个。这是我在Haskell中第一次真正尝试并发编程,我遇到了一些麻烦 我的想法是将列表分为十个元素的子列表,然后mapM一个函数,该函数同时生成十个命令中的每一个,等待每个命令完成后再进入下一组十个。然而,我使用/采取的每一种不同的库/方法似乎只是同时启动列表中的每个命令 假设我有最简单的函数来执行shell命令: import System.Process execShellCommand :: String ->
mapM
一个函数,该函数同时生成十个命令中的每一个,等待每个命令完成后再进入下一组十个。然而,我使用/采取的每一种不同的库/方法似乎只是同时启动列表中的每个命令
假设我有最简单的函数来执行shell命令:
import System.Process
execShellCommand :: String -> IO ()
execShellCommand cmd = void $ createProcess (shell cmd)
天真的方法
import Control.Monad
import Data.List.Split.Internals
runChunks :: [String] -> IO ()
runChunks as = mapM_ (mapM_ execShellCommand) $ chunksOf 10 as
一次执行列表中的所有命令(我尝试使用conductor.Process中的waitFor
函数,结果类似)。让我们更仔细地考虑一下,重新定义函数execShellCommand
,以使用控件。Concurrent
:
import Control.Concurrent
execShellCommand :: String -> IO ()
execShellCommand cmd = do
m <- newEmptyMVar
r <- void $ createProcess (shell cmd)
forkIO $ putMVar m r
takeMVar m
runChunks :: [String] -> IO ()
runChunks [] = return ()
runChunks as = do
mapM_ execShellCommand $ take 10 as
runChunks $ drop 10 as
导入控制。并发
EXECSHELL命令::字符串->IO()
execShellCommand cmd=do
m IO()
runChunks[]=返回()
runchunk as=do
ck我有点好奇你用waitFor
尝试了什么。这是我的第一次尝试:
import System.Process
commands = ["./demo.sh " ++ show n | n <- [1..10]]
chunksOf _ [] = []
chunksOf n xs = take n xs : chunksOf n (drop n xs)
spawn cmd = do
(_,_,_,proc) <- createProcess (shell cmd)
return proc
spawnAndAwaitGroup cmds = do
procs <- mapM spawn cmds
mapM_ waitForProcess procs
main = do
mapM_ spawnAndAwaitGroup (chunksOf 3 commands)
输出:
2 starting
1 starting
3 starting
3 ending
1 ending
2 ending
4 starting
5 starting
6 starting
4 ending
5 ending
6 ending
7 starting
8 starting
9 starting
7 ending
8 ending
9 ending
10 starting
10 ending
值得注意的是,这是一个纯粹的顺序程序,在Haskell级别上不是并发的。它相当于此shell脚本:
./demo.sh 1 &
./demo.sh 2 &
./demo.sh 3 &
wait
./demo.sh 4 &
./demo.sh 5 &
./demo.sh 6 &
wait
./demo.sh 7 &
./demo.sh 8 &
./demo.sh 9 &
wait
./demo.sh 10 &
wait
所有并发行为都发生在操作系统级别,即派生进程的交互中 无关:不应导入内部
模块。在这种情况下,您可以导入数据.List.Split
。有关不涉及分块的另一种方法,请参阅此答案。
2 starting
1 starting
3 starting
3 ending
1 ending
2 ending
4 starting
5 starting
6 starting
4 ending
5 ending
6 ending
7 starting
8 starting
9 starting
7 ending
8 ending
9 ending
10 starting
10 ending
./demo.sh 1 &
./demo.sh 2 &
./demo.sh 3 &
wait
./demo.sh 4 &
./demo.sh 5 &
./demo.sh 6 &
wait
./demo.sh 7 &
./demo.sh 8 &
./demo.sh 9 &
wait
./demo.sh 10 &
wait