LoginSignup
19

More than 5 years have passed since last update.

Haskellでマルチスレッド処理

Posted at

Control.Concurrentを使うとHaskellでもマルチスレッド処理ができます。
よく使う函数は(多分)以下の通り。

forkIO :: IO () -> IO ThreadId -- IO ()を渡すとその場で実行
killThread :: ThreadId -> IO () -- 指定のThreadをkillする
threadDelay :: Int -> IO () -- スレッドを指定の時間[microsec]だけ停止する

data MVar a -- スレッド内で使えるmutableな変数
newMVar :: a -> IO (MVar a) -- 変数を初期化
takeMVar :: MVar a -> IO a -- 変数の値を取り出す
putMVar :: MVar a -> a -> IO () -- 変数に代入する

サンプルコードその1

import Control.Concurrent
import Control.Monad

waiting :: Int -> IO ()
waiting n = do
  putStrLn $ "waiting" ++ (replicate n '.')
  threadDelay 100000
  waiting (n+1)

doSth :: IO Bool
doSth = do
  -- do something
  threadDelay 3000000
  putStrLn $ "=========== done ========="
  threadDelay 3000000
  putStrLn $ "=========== done ========="
  threadDelay 3000000
  putStrLn $ "=========== done ========="

  return True

ex1 = do
  w <- forkIO $ waiting 0
  u <- doSth
  when u $ killThread w
  putStrLn "killed the waiting thread"

doSthスレッドは「3秒かかる処理」を3回行います。
waitingスレッドは"waiting..."というメッセージを出力します。処理が3回終わったところで待ちスレッドをkillしておしまいです。

サンプルコードその2

import Control.Concurrent
import Control.Monad

waiting :: Int -> IO ()
waiting n = do
  putStrLn $ "waiting" ++ (replicate n '.')
  threadDelay 100000
  waiting (n+1)

doSthWithMVar :: MVar Bool -> IO ()
doSthWithMVar ref = do
  threadDelay 3000000
  putStrLn $ "=========== done ========="
  threadDelay 3000000
  putStrLn $ "=========== done ========="
  threadDelay 3000000
  putStrLn $ "=========== done ========="

  putMVar ref True

ex2 = do
  ref <- newMVar False
  w <- forkIO $ waiting 0
  _ <- forkIO $ doSthWithMVar ref

  go ref w

  where
    go :: MVar Bool -> ThreadId -> IO ()
    go ref w = do
      tf <- takeMVar ref
      case tf of
        True -> do
          killThread w
          putStrLn "killed the waiting thread"
        False -> go ref w

大体さっきと同じですが、今回はMVarを使ってフラグを管理しています。
doSthWithMVarは、3秒かかる処理を3回したあとフラグをTrueにします。
ex2は2つのスレッドを立ち上げたあとループに入ります(go)。フラグがTrueになったらスレッドをkillしてループを抜けます。

これだけ!

まとめ

  • Control.ConcurrentのThreadはとても簡単で使いやすい
  • MVarを使えばスレッド間で共有したいmutableな変数を作成することができる
  • こころなしか(特に日本語)ググってもサンプル・チュートリアルが少ないような…[要出典]

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19