2016-02-26 2 views
4

Скажем, я делаю это:Будущее всегда создает новый поток?

(future 
    (do-the-thing)) 

Могу ли я гарантировать, что, независимо от того, что (do-the-thing) делает,

  • совершенно новый поток будет создан, а не получать один из бассейна или что-нибудь подобное что?
  • ничего, кроме (do-the-thing), никогда не будет работать на этой новой теме?
  • раз (do-the-thing) выполняет эту новую нить, поток прекратится?

Если нет, то при каких обстоятельствах эти предположения будут ложными?

+0

Мое понимание заключается в том, что фьючерсы в Clojure, когда не используются специализированные библиотеки, не более чем Java-фьючерсы. Так что это, возможно, уже было задано и ответили как вопрос Java. –

+0

@ChrisMurphy Если бы вы могли связать меня с вопросом Java, это было бы отлично! –

+0

Блок фьючерсов Java, в то время как Scala - нет. Однако этот недостаток в Clojure был исправлен с помощью этой [библиотеки] (https://github.com/leonardoborges/imminent). –

ответ

4

Короткий ответ Нет

От Clojure-х core.clj:

(defmacro future 
... 
    [& body] `(future-call (^{:once true} fn* [] [email protected]))) 
... 

(defn future-call 
... 
    [f] 
    (let [f (binding-conveyor-fn f) 
     fut (.submit clojure.lang.Agent/soloExecutor ^Callable f)] 
... 

Так исполнителем будущего clojure.lang.Agent/soloExecutor.

От Agent.java:

volatile public static ExecutorService soloExecutor = Executors.newCachedThreadPool(
    createThreadFactory("clojure-agent-send-off-pool-%d", sendOffThreadPoolCounter)); 

Вы можете видеть, что soloExecutor создается Executors.newCachedThreadPool()

От document of Executors.newCachedThreadPool:

Создает пул потоков, который создает новые темы, по мере необходимости, но будет повторно использовать ранее построенные потоки, когда они доступны. Эти пулы обычно улучшают производительность программ, выполняющих многие недолговечные асинхронные задачи. Вызовы для выполнения будут повторно использовать ранее созданные потоки, если они доступны. Если существующий поток недоступен, новый поток будет создан и добавлен в пул. Нити, которые не использовались в течение шестидесяти секунд, прекращаются и удаляются из кеша. Таким образом, пул, который остается бездействующим достаточно долго, не будет потреблять какие-либо ресурсы. Обратите внимание, что пулы со схожими свойствами, но разные детали (например, параметры тайм-аута) могут создаваться с использованием конструкторов ThreadPoolExecutor.

Таким образом, ответ другой работы (do-the-thing) может выполняться в том же потоке, и поток будет прекращен через 60 секунд, если больше нет работы.

Вы можете подтвердить поведение Executors.newCachedThreadPool в следующем коде:

(doseq [i (for [x (range 10)] (future (Thread/sleep 1000) (.getId (Thread/currentThread))))] (print @i) (print " ")) 

Выполнение этого кода в Clojure консоли, вы получите:

50 49 48 47 46 45 44 43 42 41 nil 

впервые. И запустите его снова через 5 секунд, вы получите:

50 49 43 41 45 42 46 47 48 44 nil 

Поэтому вы можете подтвердить, что нить используется повторно.

Если выполнить этот код после 60 секунд, вы получите:

60 59 58 57 56 55 54 53 52 51 nil 

Таким образом, вы можете подтвердить, что предыдущие темы были прекращены и были созданы новые потоки.

+0

На всякий случай заинтересованы люди: 'core.async' использует' newFixedThreadPool': http://stackoverflow.com/questions/949355/java-newcachedthreadpool-versus-newfixedthreadpool – ClojureMostly

Смежные вопросы