Inspired by a tutorial about akka tutorial in Scala about making a concurrent PI calculator, I made similar on in Clojure without actor model but just with thread and atom.
(ns pi.core
(:import [java.util.concurrent Executors])
(:gen-class))
(def sum (partial reduce +))
(defn f [n]
(/ (if (even? n) 1 -1) (inc (* 2 n))))
(defn solver1 [n]
(double (* 4 (sum (map f (range 0 n))))))
(defn solver2 [n]
(def a (atom 0))
(def tasks
(let [unit (/ n 4)]
(for [m (range 0 4)]
(fn []
(swap! a (partial + (sum (map f (range (* unit m) (* unit (inc m)))))))))))
(let [pool (Executors/newFixedThreadPool (count tasks))]
(doseq [f (.invokeAll pool tasks)]
(.get f))
(.shutdown pool))
(double (* 4 @a)))
(defn -main []
(let [n 2000]
(prn (solver1 n))
(prn (solver2 n))))
Commenting out the line of solver1/solver2, I got the following results on my 2-core with hyper-threading machine; virtually it's 4 core machine.
solver1
real 3.80
user 4.66
sys 0.09
3.141092653621043
solver2
real 2.01
user 3.44
sys 0.05
3.141092653621043
Comparing to the sequential version, the concurrent version was almost 2 times faster.