2013-05-03 17 views
13

Próbuję zrozumieć futures Scala pochodzących z Java tle: Rozumiem, można napisać:Scala - futures i współbieżności

val f = Future { ... } 

to mam dwa pytania:

  1. Jak to przyszłość zaplanowane ? Automatycznie?
  2. Jakiego programu planującego użyje? W Javie byłoby użyć wykonawcę, które mogą być puli wątków itp

Ponadto, jak mogę osiągnąć scheduledFuture, ten, który wykonuje po określonym opóźnieniem? Dzięki

+1

Jeśli chcesz kontrolować bezpośrednio, kiedy przyszła przyszłość, powinieneś użyć obietnicy. –

+1

Obietnice są nieco inne - są w zasadzie "Przyszłością" widziane z widoku executora (tj. Kontener jednokrotnego zapisu, w którym musi w pewnym momencie wstawić wartość). Osoba dzwoniąca/klient nie ma możliwości bezpośredniego użycia 'Promise' do kontrolowania harmonogramu. –

Odpowiedz

11

Blok Future { ... } jest cukrem syntaktycznym dla połączenia z Future.apply (jak na pewno znasz Macieja), przekazując blok kodu jako pierwszy argument.

Patrząc na docs for this method widać, że przyjmuje on domyślnie ExecutionContext - i to właśnie ten kontekst określa sposób jego wykonania. W ten sposób, aby odpowiedzieć na twoje drugie pytanie, przyszłość będzie wykonywana przez dowolny obiekt ExecutionContext w ukrytym zakresie (i oczywiście jeśli jest niejednoznaczny, jest to błąd podczas kompilacji).

W wielu przypadkach będzie to numer z import ExecutionContext.Implicits.global, który może zostać zmodyfikowany przez właściwości systemu, ale domyślnie używa ThreadPoolExecutor z jednym gwintem na rdzeń procesora.

Planowanie to jednak inna sprawa. W przypadku niektórych przypadków użycia możesz podać własny ExecutionContext, który zawsze zastosował to samo opóźnienie przed wykonaniem. Ale jeśli chcesz, aby opóźnienie było kontrolowane ze strony wywoławczej, oczywiście nie możesz użyć Future.apply, ponieważ nie ma parametrów informujących o tym, jak należy to zaplanować. Proponuję przesłanie zadań bezpośrednio do planowego wykonawcy w tym przypadku.

+0

Yhanks Andrzej - pomocny jak zawsze :) – Bober02

3

Odpowiedź Andrzeja już obejmuje większość pytań. Warto wspomnieć, że "domyślny" domyślny kontekst wykonania Scala (import scala.concurrent.ExecutionContext.Implicits._) jest dosłownie a java.util.concurrent.Executor, a cała koncepcja ExecutionContext jest bardzo cienkim opakowaniem, ale jest ściśle dopasowana do szkieletu wykonawczego Javy.

Aby osiągnąć coś podobnego do planowanych kontraktów terminowych, jak zauważa Mauricio, będziesz musiał użyć obietnic i mechanizmu planowania stron trzecich.

Brak wspólnego mechanizmu dla tego wbudowanego w Scala 2.10 Futures to szkoda, ale nic fatalnego.

Obietnica jest uchwytem do obliczeń asynchronicznych. Tworzysz jedną (przyjmując zakres ExecutionContext), dzwoniąc pod numer val p = Promise[Int](). Właśnie obiecaliśmy liczbę całkowitą.
Klienci mogą zdobyć przyszłość, która zależy od spełnienia obietnicy, po prostu dzwoniąc pod numer p.future, który jest tylko przyszłością Scala.
Spełnienie obietnicy jest po prostu kwestią dzwonienia pod numer p.successful(3), w którym momencie zakończy się przyszłość.

Odtwarzanie 2.x rozwiązuje planowanie przy użyciu obietnic i zwykłego starego zegara Java 1.4.
Here to linkrot-proof link do źródła.

Załóżmy również spojrzeć na źródło tutaj:

object Promise { 
    private val timer = new java.util.Timer() 

    def timeout[A](message: => A, duration: Long, unit: TimeUnit = TimeUnit.MILLISECONDS) 
       (implicit ec: ExecutionContext): Future[A] = { 
    val p = Promise[A]() 
    timer.schedule(new java.util.TimerTask { 
     def run() { 
     p.completeWith(Future(message)(ec)) 
     } 
    }, unit.toMillis(duration)) 
    p.future 
    } 
} 

ten może być następnie wykorzystane w taki sposób:

val future3 = Promise.timeout(3, 10000) // will complete after 10 seconds 

Wskazówka ta jest o wiele ładniejszy niż podłączając Thread.sleep(10000) do kodu, który zablokuje twój wątek i wymusi zmianę kontekstu.

Warto również zauważyć, że w tym przykładzie jest val p = Promise... na początku funkcji i p.future na końcu. Jest to powszechny wzorzec przy pracy z obietnicami. Rozumiem, że funkcja ta powoduje pewne obietnice dla klienta i uruchamia asynchroniczne obliczenia w celu jego spełnienia.

Aby uzyskać więcej informacji o obietnicach Scala, spójrz na here. Zauważ, że używają one małej metody future z obiektu paczki concurrent zamiast Future.apply. Ten pierwszy po prostu deleguje to drugie. Osobiście wolę małą literę future.

Powiązane problemy