Threads, Promises, and Futures
Details
Clojure functions implement Java’s Runnable
interface. Clojure vars live in thread-local storage.
Create a thread, execute a function in it, and wait for it to finish:
Same, but with multiple threads and parametrized output functions for distinction:
Same, but with many threads:
Deliver a result through a promise:
@result is syntactic sugar for (deref result). A value can only be
delivered once, but derefed multiple times.
Use a promise to communicate between threads:
Simplify concurrent code using a future, which is a promise with its own thread:
Use a timeout to deliver a fallback value if a computation takes too long:
Exercises
Countdown
Write a function countdown that expects a name and a number n
from which to count down to zero. Print the name and the number, which
is to be counted down, and then pause for a second. Continue printing
until the number reached zero.
Then write a function launch-rockets that expects a number n (the
number of rockets to be launched) and sec (the number of seconds
from which to count down to zero). Create one thread per rocket,
i.e. n threads, which execute the contdown function with the name
rocket X, where X is a number from 1 to n. Start those threads.
Hint: Use (locking *out* (println OUTPUT)) to make the output in
countdown thread-safe.
Test: (launch-rockets 3 4) shall produce the following (non-deterministic) output:
Map in Parallel
Write a function factor that performs prime factorization without
any promises or futures and calculates the prime factors
synchronuously.
Then write a function factors that accepts a sequence of numbers,
which shall be factorized using the factor function just written,
but doing so in parallel.
Hint: Integer factorization
(Wikipedia)
describes how a number can be factorized into its prime factors. Use
the solution for the Lazy Prime
Numbers exercise to get
candidates for prime factors. Use the pmap function as a concurrent
version of map.
Test: (factor (factors (take 10 (iterate inc 10))) shall return ([2 5] [11] [2 2 3] [13] [2 7] [3 5] [2 2 2 2] [17] [2 3 3] [19]).
Prime Factors Promise
Write a function factor-prom that expects a parameter x, which is
an integer to be factorized into its prime factors, and returns a
promise that delivers a sequence of that number’s prime factors. The
actual computation shall take place in its own thread.
Hint: Re-use the factor function from the last exercise.
Test: @(factor-prom 324) shall return [2 2 3 3 3 3].
Prime Factors Future
Write a function factor-fut that performs the same computation as
factor-prom from the exercise before, but returns a future instead
of a promise.
Hint: Start from factor-prom of the last exercise and simplify its
code.
Test: @(factor-fut 324) shall return [2 2 3 3 3 3].