Let's say I do this:
(future
(do-the-thing))
Am I guaranteed that, regardless of what (do-the-thing)
does,
(do-the-thing)
will ever run on that new thread?(do-the-thing)
executes on that new thread, the thread will terminate?If not, under what circumstances would these assumptions be false?
A Future interface provides methods to check if the computation is complete, to wait for its completion and to retrieve the results of the computation. The result is retrieved using Future's get() method when the computation has completed, and it blocks until it is completed.
Think of a Future as an object that holds the result – it may not hold it right now, but it will do so in the future (once the Callable returns). Thus, a Future is basically one way the main thread can keep track of the progress and result from other threads.
A Future represents the result of an asynchronous computation. Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation.
Starting a Thread With a Runnable Thread thread = new Thread(runnable); thread. start(); When the thread is started it will call the run() method of the MyRunnable instance instead of executing it's own run() method.
Short answer is No
From clojure's core.clj:
(defmacro future
...
[& body] `(future-call (^{:once true} fn* [] ~@body)))
...
(defn future-call
...
[f]
(let [f (binding-conveyor-fn f)
fut (.submit clojure.lang.Agent/soloExecutor ^Callable f)]
...
So the executor of the future is clojure.lang.Agent/soloExecutor
.
From Agent.java:
volatile public static ExecutorService soloExecutor = Executors.newCachedThreadPool(
createThreadFactory("clojure-agent-send-off-pool-%d", sendOffThreadPoolCounter));
You can see that soloExecutor
is created by Executors.newCachedThreadPool()
From document of Executors.newCachedThreadPool:
Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available. These pools will typically improve the performance of programs that execute many short-lived asynchronous tasks. Calls to execute will reuse previously constructed threads if available. If no existing thread is available, a new thread will be created and added to the pool. Threads that have not been used for sixty seconds are terminated and removed from the cache. Thus, a pool that remains idle for long enough will not consume any resources. Note that pools with similar properties but different details (for example, timeout parameters) may be created using ThreadPoolExecutor constructors.
So the answer is some other job of (do-the-thing)
may be executed in same thread, and the thread will be terminated after 60 seconds if there's no more job.
You can confirm the behavior of Executors.newCachedThreadPool
in following code:
(doseq [i (for [x (range 10)] (future (Thread/sleep 1000) (.getId (Thread/currentThread))))] (print @i) (print " "))
Executing this code in clojure console, you get:
50 49 48 47 46 45 44 43 42 41 nil
for first time. And execute it again after 5 seconds, you get:
50 49 43 41 45 42 46 47 48 44 nil
Therefore you can confirm that the thread is reused.
If you execute same code after 60 seconds, you get:
60 59 58 57 56 55 54 53 52 51 nil
So you can confirm that previous threads were terminated and new threads were created.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With