2016-11-01 4 views
0

Это должно быть просто, но я понятия не имею, как это сделать. Я хочу запустить ScalaZ Task в текущем потоке. Я был удивлен, что task.run не работает в текущем потоке, так как он синхронный.Как запустить ScalaZ Задача в текущей теме

Возможно ли запустить его в текущей теме и как это сделать?

+0

Посмотрите на описание unsafeStart отсюда. http://timperrett.com/2014/07/20/scalaz-task-the-missing-documentation/ –

ответ

0

С http://timperrett.com/2014/07/20/scalaz-task-the-missing-documentation/ произошли некоторые изменения и стирания.

Сейчас рекомендуемый способ вызова задачи синхронно является:

task.unsafePerformSync  // returns result or throws exception 
task.unsafePerformSyncAttempt // returns -\/(error) or \/-(result) 

Имейте в виду, однако, что это не совсем сделано в потоке вызывающего - исполнение является проведенными в пуле потоков, определенной для но поток потока вызывающего абонента до завершения выполнения. Невозможно выполнить задачу точно в той же теме.

+0

Это не совсем правильно, «исполнение выполняется в пуле потоков, определенном для задачи». Рассмотрим эту «Task.delay (« aaa »). Map (_ + 1)'. Он запрашивал какой-либо пул потоков во время компиляции? – dk14

0

В общем, если Task.async используется - нет никакого способа, чтобы сделать композит Task всегда оставаться в том же потоке, как cb (обратный вызов) может быть вызвана из любого места (любая тема), так что в цепи, как:

Task 
    .delay("aaa") 
    .map(_ + "bbb") 
    .flatMap(x => Task.async(cb => completeCallBackSomewhereElse(cb, x))) 
    .map(_ + "ccc") 
    .unsafePerformSync 

_ + "bbb" собирается быть выполнен в потоке вызывающего абонента

_ + "ccc" собирается быть выполнен в потоке Somewhereelse «s, как scalaz не имеет никакого контроля над ним.

В принципе, это позволяет Task быть мощным инструментом для асинхронных операций, поэтому он может даже не знать о пулах потоков или даже реализовать поведение без чистых потоков и ждать/уведомлять.

Однако существуют специальные случаи, когда он может работать в качестве абонентов спусков:

1) Нет Strategy/Task.async связанные вещи:

Task.delay("aaa").map(_ + "bbb").unsafePerformSync 

unsafePerformSync использует CountDownLatch ждать результата от runAsync, так если на пути нет асинхронных/недетерминированных операций - runAsync будет использовать caller's thread:

/** 
    * Run this `Future`, passing the result to the given callback once available. 
    * Any pure, non-asynchronous computation at the head of this `Future` will 
    * be forced in the calling thread. At the first `Async` encountered, control 
    * switches to whatever thread backs the `Async` and this function returns. 
    */ 
    def runAsync(cb: A => Unit): Unit = 
    listen(a => Trampoline.done(cb(a))) 

2) У вас есть контроль над стратегиями исполнения. Так что this simple Java trick поможет. Кроме того, это уже реализовано в scalaz и называется Strategy.sequential


P.S.

1) Если вы просто хотите начать вычисление как можно скорее, используйте task.now/Task.unsafeStart.

2) Если вы хотите что-то не так сильно связанное с асинхронными вещами, но по-прежнему ленивое и стек-сейфом, вы можете взглянуть здесь (это для библиотеки Cats) http://eed3si9n.com/herding-cats/Eval.html

3) Если вам просто нужно инкапсулировать сторону -эффекты - взгляните на scalaz.effect

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