http://gauche.svn.sourceforge.net/viewvc/gauche/Gauche-threadlib/trunk/concurrent/executor.scm
<thread-pool-executor>はスレッドプールを抽象化したクラスです。java.util.concurrent.ThreadPoolExecutorをGaucheで実装しました。
<thread-pool-executor>のインスタンスはmakeで作成します。インスタンスの作成時に引数を渡してスレッドプールの構成をカスタマイズすることができます。
(make <thread-pool-executor> :core-pool-size core-pool-size :maximum-pool-size maximum-pool-size :keep-alive-time keep-alive-time :work-queue work-queue :rejected-execution-handler rejected-execution-handler)
タスクのサブミットはexecutor-submitで行います。
(executor-submit executor thunk)
thunkをラップしたfutureオブジェクトが返ります。返り値にfuture-getを呼ぶと、thunkがスレッドプールで実行されたあと、その値が結果として返ります。
スレッドプールの終了はexecutor-shutdown!、終了処理の完了を待つのはexecutor-await-terminationで行います。
(executor-shutdown! executor) (executor-await-termination executor timeout)
スレッドプールを使って簡単なmapreduceを書いてみましょう。タスクの特性によって結果は異なりますが、マルチコアシステムではタスクを分割して並行に実行することで性能が向上することがあります。
(define (simple-mapreduce nthread mapper reducer lis) (let1 executor (make-thread-pool-executor nthread) (define (submit-task data) (executor-submit executor (lambda () (mapper data)))) (begin0 (reducer (map future-get (map submit-task lis))) (executor-shutdown! executor))))
このsimple-mapreduceは、nthread個のスレッドを持つスレッドプールを作成して、lisの各要素についてmapperを呼びます。mapperはスレッドプールで実行されます。最後にreducerが結果をまとめることが期待されています。