Asynchronous Programming with Future &
Promises
Asynchronous Programming with Future &
Promises
Satendra Kumar
Software Consultant
Knoldus Software LLP
Satendra Kumar
Software Consultant
Knoldus Software LLP
Topics CoveredTopics Covered
Future
Callback Handler
Functional Composition
For-Comprehension
Blocking Future
Promises
Live Demo
Executor Services
Choosing-executor service
Best practices
Future
Callback Handler
Functional Composition
For-Comprehension
Blocking Future
Promises
Live Demo
Executor Services
Choosing-executor service
Best practices
import org.apache.commons.io.IOUtils
import org.apache.http.client.methods.HttpGet
import org.apache.http.impl.client.HttpClientBuilder
object FacebookPage {
private val homeURL = "https://graph.facebook.com/v2.0/"
private val accessToken = "CAAVHCxa"
private val url = s"$homeURL${"25"}/feed?method=GET&format=json&access_token=$
{accessToken}"
def getFeeds(): String = {
val request = new HttpGet(url)
val client = HttpClientBuilder.create().build();
val response = client.execute(request)
IOUtils.toString(response.getEntity().getContent())
}
}
object FacebookFeedParser {
implicit val formats = DefaultFormats
def parse(facebookFeeds: String): List[FacebookPageFeed] = {
val parsedFacebookFeeds = net.liftweb.json.parse(facebookFeeds)
(parsedFacebookFeeds  "data").children map { facebookfeed =>
val contentId = (facebookfeed  "id")
val date = (facebookfeed  "created_time")
val content = (facebookfeed  "message")
FacebookPageFeed(contentId, date, content)
}
}
implicit def extract(json: JValue): String = json match {
case JNothing => ""
case data => data.extract[String]
}
}
case class FacebookPageFeed(id: String, date: String, content: String)
object DemoApp extends App {
val facebookFeeds = FacebookPage.getFeeds()
val parsedFacebookFeed = FacebookFeedParser.parse(facebookFeeds)
val result = FacebookRepository.save(parsedFacebookFeed)
// do some other tasks
}
object DemoApp extends App {
val facebookFeeds = FacebookPage.getFeeds()
val parsedFacebookFeed = FacebookFeedParser.parse(facebookFeeds)
val result = FacebookRepository.save(parsedFacebookFeed)
// do some other tasks
}
Something wrong ?
object DemoApp extends App {
val facebookFeeds = FacebookPage.getFeeds()
val parsedFacebookFeed = FacebookFeedParser.parse(facebookFeeds)
val result = FacebookRepository.save(parsedFacebookFeed)
// do some other tasks
}
This is blocking
Scala's Futures API
Scala's Futures API
➢ Futures provide a nice way to reason about performing many operations in parallel–
in an efficient and non-blocking way.
Scala's Futures API
➢ Futures provide a nice way to reason about performing many operations in parallel–
in an efficient and non-blocking way.
➢ The idea is simple, a Future is a sort of a placeholder object that you can
create for a result that does not yet exist. Generally, the result of the Future is
computed concurrently and can be later collected. Composing concurrent
tasks in this way tends to result in faster, asynchronous, non-blocking parallel
code.
Scala's Futures API
➢ Futures provide a nice way to reason about performing many operations in parallel–
in an efficient and non-blocking way.
➢ The idea is simple, a Future is a sort of a placeholder object that you can
create for a result that does not yet exist. Generally, the result of the Future is
computed concurrently and can be later collected. Composing concurrent
tasks in this way tends to result in faster, asynchronous, non-blocking parallel
code.
➢ By default, futures and promises are non-blocking, making use of callbacks
instead of typical blocking operations.
Scala's Futures API
➢ Futures provide a nice way to reason about performing many operations in parallel–
in an efficient and non-blocking way.
➢ The idea is simple, a Future is a sort of a placeholder object that you can
create for a result that does not yet exist. Generally, the result of the Future is
computed concurrently and can be later collected. Composing concurrent
tasks in this way tends to result in faster, asynchronous, non-blocking parallel
code.
➢ By default, futures and promises are non-blocking, making use of callbacks
instead of typical blocking operations.
➢ Blocking is still possible - for cases where it is absolutely necessary, futures
can be blocked on (although this is discouraged).
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import com.knol.facebook.FacebookPage
object DemoApp extends App {
val facebookFeeds: Future[String] = Future {
FacebookPage.getFeeds()
}
}
def apply[T](body: =>T)(implicit executor: ExecutionContext): Future[T]
Future's apply method
Implicit Execution Context
object Implicits {
implicit lazy val global: ExecutionContextExecutor =
impl.ExecutionContextImpl.fromExecutor(null: Executor)
}
Explicit Execution Context
➢ We can specify own ExecutionContext , instead of importing the global implicit ExecutionContext.
import java.util.concurrent.Executors
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import com.knol.facebook.FacebookPage
import scala.concurrent.ExecutionContextExecutor
import java.util.concurrent.ExecutorService
object DemoApp extends App {
val noOfThread = 10
val threadPool:ExecutorService = Executors.newFixedThreadPool(noOfThread)
val ec: ExecutionContextExecutor = ExecutionContext.fromExecutor(threadPool)
val facebookFeeds = Future {
FacebookPage.getFeeds()
}(ec)
}
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import com.knol.facebook.FacebookPage
object DemoApp extends App {
val facebookFeeds: Future[String] = Future {
FacebookPage.getFeeds()
}
}
Future completion can take one of two forms:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import com.knol.facebook.FacebookPage
object DemoApp extends App {
val facebookFeeds: Future[String] = Future {
FacebookPage.getFeeds()
}
}
Future completion can take one of two forms:
a)When a Future is completed with a value, we say that the future was
successfully completed with that value.
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import com.knol.facebook.FacebookPage
object DemoApp extends App {
val facebookFeeds: Future[String] = Future {
FacebookPage.getFeeds()
}
}
Future completion can take one of two forms:
a)When a Future is completed with a value, we say that the future was
successfully completed with that value.
b)When a Future is completed with an exception thrown by the
computation, we say that the Future was failed with that exception.
Callbacks
Callbacks
➢ We now know how to start an asynchronous computation to create a new future value, but we
have not shown how to use the result once it becomes available, so that we can do something
useful with it.
Callbacks
➢ We now know how to start an asynchronous computation to create a new future value, but we
have not shown how to use the result once it becomes available, so that we can do something
useful with it.
➢ We can get result by registering a callback on the future.
Callbacks
➢ We now know how to start an asynchronous computation to create a new future value, but we
have not shown how to use the result once it becomes available, so that we can do something
useful with it.
➢ We can get result by registering a callback on the future.
➢ This callback is called asynchronously once the future is completed. If the future has already
been completed when registering the callback, then the callback may either be executed
asynchronously, or sequentially on the same thread.
Callbacks
def onSuccess[U](pf: PartialFunction[T, U])(implicit executor:ExecutionContext): Unit
def onFailure[U](pf:PartialFunction[Throwable,U])(implicit executor:ExecutionContext): Unit
def onComplete[U](f: Try[T] => U)(implicit executor: ExecutionContext): Unit
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import com.knol.facebook.FacebookPage
object DemoApp extends App {
val facebookFeeds: Future[String] = Future {
FacebookPage.getFeeds()
}
facebookFeeds onSuccess {
case feeds => println(feeds)
}
}
onSuccess
onFailure
object DemoApp extends App {
val facebookFeeds: Future[String] = Future {
FacebookPage.getFeeds()
}
facebookFeeds onFailure {
case feeds:Throwable =>
println("Error getting feeds "+feeds.getMessage)
}
}
onComplete
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import com.knol.facebook.FacebookPage
import scala.util.Success
import scala.util.Failure
object DemoApp extends App {
val facebookFeeds: Future[String] = Future {
FacebookPages.getFeeds()
}
facebookFeeds onComplete {
case Success(feeds) => println("feeds " + feeds)
case Failure(ex) => println("Error "+ex.getMessage)
}
}
Callbacks
➢ Callbacks registered on the same future are unordered.
➢ There is no guarantee it will be called by the thread that completed the future or the
thread which created the callback. Instead, the callback is executed by some thread,
at some time after the future object is completed.
➢ Registering a callback on the future which is already completed will result in the
callback being executed eventually.
➢ Once executed, the callbacks are removed from the future object, thus being eligible
for GC
Functional Composition
Futures provide combinators which allow a more straightforward composition.
def map[S](f: T => S)(implicit executor: ExecutionContext): Future[S]
def flatMap[S](f: T => Future[S])(implicit executor: ExecutionContext): Future[S]
def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit ec: ExecutionContext): Future[U]
def recoverWith[U >: T](pf: PartialFunction[Throwable,Future[U]])(implicit ec: ExecutionContext):Future[U]
def foreach[U](f: T => U)(implicit executor: ExecutionContext): Unit
def fallbackTo[U >: T](that: Future[U]): Future[U]
def andThen[U](pf: PartialFunction[Try[T], U])(implicit executor: ExecutionContext): Future[T]
def mapTo[S](implicit tag: ClassTag[S]): Future[S]
def sequence[A, M[X] <: TraversableOnce[X]](in: M[Future[A]])(
implicit cbf: CanBuildFrom[M[Future[A]], A, M[A]], executor: ExecutionContext): Future[M[A]]
map
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.util.Failure
import scala.util.Success
import com.knol.facebook.FacebookPage
import com.knol.facebook.FacebookFeedParser
import com.knol.facebook.FacebookPageFeed
object DemoApp extends App {
val facebookFeeds: Future[String] = Future {
FacebookPage.getFeeds()
}
val feedList: Future[List[FacebookPageFeed]] = facebookFeeds map { feed =>
FacebookFeedParser.parse(feed)
}
feedList onComplete {
case Success(feeds) => feeds foreach println
case Failure(ex) => println("Error getting feed " + ex.getMessage)
}
}
flatMap
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.util.Failure
import scala.util.Success
import com.knol.facebook.FacebookPage
import com.knol.facebook.FacebookFeedParser
import com.knol.facebook.FacebookPageFeed
object DemoApp extends App {
val facebookFeeds: Future[String] = Future {
FacebookPage.getFeeds()
}
val feedList: Future[List[FacebookPageFeed]] = facebookFeeds flatMap { feed =>
FacebookFeedParser.parse(feed)
}
feedList onComplete {
case Success(feeds) => feeds foreach println
case Failure(ex) => println("Error getting feed " + ex.getMessage)
}
}
foreach
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.util.Failure
import scala.util.Success
import com.knol.facebook.FacebookPage
import com.knol.facebook.FacebookFeedParser
import com.knol.facebook.FacebookPageFeed
object DemoApp extends App {
val facebookFeeds: Future[String] = Future {
FacebookPage.getFeeds()
}
val feedList: Future[List[FacebookPageFeed]] = facebookFeeds flatMap { feed =>
FacebookFeedParser.parse(feed) }
feedList foreach println
}
recover
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.util.Failure
import scala.util.Success
import com.knol.facebook.FacebookPage
import com.knol.facebook.FacebookFeedParser
import com.knol.facebook.FacebookPageFeed
object DemoApp extends App {
val facebookFeeds: Future[String] = Future {
FacebookPage.getFeeds()
}
val feedList: Future[List[FacebookPageFeed]] = facebookFeeds map { feed =>
FacebookFeedParser.parse(feed) } recover {
case ex: Throwable => List()
}
feedList onComplete {
case Success(feeds) => feeds foreach println
case Failure(ex) => println("Error getting feed " + ex.getMessage)
}
}
recoverWith
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.util.Failure
import scala.util.Success
import com.knol.facebook.FacebookPage
import com.knol.facebook.FacebookFeedParser
import com.knol.facebook.FacebookPageFeed
object DemoApp extends App {
val facebookFeeds: Future[String] = Future {
FacebookPage.getFeeds()
}
val feedList: Future[List[FacebookPageFeed]] = facebookFeeds flatMap { feed =>
FacebookFeedParser.parse(feed) } recoverWith {
case ex: Throwable => Future { List(FacebookPageFeed("", "", "")) }
}
feedList onComplete {
case Success(feeds) => feeds foreach println
case Failure(ex) => println("Error getting feed " + ex.getMessage)
}
}
fallbackTo
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.util.Failure
import scala.util.Success
import com.knol.facebook.FacebookPage
import com.knol.facebook.FacebookFeedParser
import com.knol.facebook.FacebookPageFeed
object DemoApp extends App {
val facebookFeeds: Future[String] = Future {
FacebookPage.getFeeds()
}
val fallbackFuture: Future[String] = Future { "{}" }
val resultantFuture = facebookFeeds fallbackTo fallbackFuture
resultantFuture onComplete {
case Success(feeds) => feeds foreach println
case Failure(ex) => println("Error getting feed " + ex.getMessage)
}
}
andThen
The andThen combinator is used purely for side-effecting purposes. It returns a new future with exactly the same
result as the current future, regardless of whether the current future failed or not. Once the current future is
completed with the result, the closure corresponding to the andThen is invoked and then the new future is
completed with the same result as this future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.util._
import com.knol.facebook.FacebookPage
import com.knol.facebook.FacebookFeedParser
object DemoApp extends App {
val facebookFeeds: Future[String] = Future {
FacebookPage.getFeeds()
}
val resultantFuture = facebookFeeds andThen { case Success(feed) =>
FacebookFeedParser.parse(feed) foreach println
}
resultantFuture onComplete {
case Success(feeds) => feeds foreach println
case Failure(ex) => println("Error getting feed " + ex.getMessage)
}
}
sequence
val listOfFuture: List[Future[Int]] = List(Future(2 + 2), Future(20 + 3),
Future(2 + 347))
val combindFuture: Future[List[Int]] = Future.sequence(listOfFuture)
For-Comprehensions
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import com.knol.facebook.FacebookPage
import com.knol.facebook.FacebookFeedParser
import com.knol.facebook.FacebookPageFeed
import scala.concurrent.Await
import scala.concurrent.duration._
import scala.util.Success
import scala.util.Failure
object DemoApp extends App {
val facebookFeeds: Future[String] = Future {
println("Current Thread in future block::::::" + Thread.currentThread().getName)
FacebookPage.getFeeds()
}
val future = for {
feeds <- facebookFeeds
parsedFeed <- Future(FacebookFeedParser.parse(feeds))
} yield parsedFeed
future onComplete {
case Success(feeds) => println("Feeds:::::::::::" + feeds)
case Failure(ex) => println("Error:::::::::::" + ex.getMessage)
}
}
Blocking
● blocking on a future is strongly discouraged for the sake of performance and for the prevention
of deadlocks. Callbacks and combinators on futures are a preferred way to use their results.
However, blocking may be necessary in certain situations and is supported by the Futures and
Promises API.
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import com.knol.facebook.FacebookPage
import com.knol.facebook.FacebookFeedParser
import com.knol.facebook.FacebookPageFeed
import scala.concurrent.Await
import scala.concurrent.duration._
object DemoApp extends App {
val facebookFeeds: Future[String] = Future {
FacebookPage.getFeeds()
}
val result = Await.result(facebookFeeds, 10 seconds)
println(result)
}
Promises
Promises
➢ Promise is an object which can be completed with a value or failed with an exception.
Promises
➢ Promise is an object which can be completed with a value or failed with an exception.
➢ While futures are defined as a type of read-only placeholder object created for a result which
doesn’t yet exist, a promise can be thought of as a writable, single-assignment container,
which completes a future. That is, a promise can be used to successfully complete a future with
a value (by “completing” the promise) using the success method. Conversely, a promise can
also be used to complete a future with an exception, by failing the promise, using the failure
method.
Promises
➢ Promise is an object which can be completed with a value or failed with an exception.
➢ While futures are defined as a type of read-only placeholder object created for a result which
doesn’t yet exist, a promise can be thought of as a writable, single-assignment container,
which completes a future. That is, a promise can be used to successfully complete a future with
a value (by “completing” the promise) using the success method. Conversely, a promise can
also be used to complete a future with an exception, by failing the promise, using the failure
method.
➢ A promise p completes the future returned by p.future. This future is specific to the promise p.
Depending on the implementation, it may be the case that p.future eq p.
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import com.knol.facebook.FacebookPage
import scala.concurrent.duration._
import scala.util.Success
import scala.util.Failure
import scala.concurrent.Promise
object PromiseDemo extends App {
val promise = Promise[String]
val future = promise.future
Future {
val feeds = FacebookPage.getFeeds()
promise success feeds
}
future onComplete {
case Success(feeds) => println("Feeds:::::::::::" + feeds)
case Failure(ex) => println("Error:::::::::::" + ex.getMessage)
}
}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.concurrent.Promise
import com.knol.facebook.FacebookPage
object PromiseDemo {
def asynExecute: Future[String] = {
val promise = Promise[String]
Future {
//do other task
val feeds = FacebookPage.getFeeds()
promise success feeds
//do other task
}
promise.future
}
}
1) Write a method that return a future that is never completed
1) Write a method that return a future that is never completed
def never[T]: Future[T] = Promise[T].future
1) Write a method that return a future that is never completed
def never[T]: Future[T] = Promise[T].future
2) Write a method that return a future with a unit value that is completed after time `t`
1) Write a method that return a future that is never completed
def never[T]: Future[T] = Promise[T].future
2) Write a method that return a future with a unit value that is completed after time `t`
def delay(t: Duration): Future[Unit] =
Future { Try(Await.ready(Promise().future, t)) }
Executor Services
● FixedThreadPool
● CachedThreadPool
● SingleThreadExecutor
● ForkJoinPool
FixedThreadPool
● It is fixed size thread pool
Executors utility class have factory methods for creating FixedThreadPool:
1) static ExecutorService newFixedThreadPool(int nThreads)
Creates a thread pool that reuses a fixed number of threads operating off a shared
unbounded queue.
2) static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory
threadFactory)
Creates a thread pool that reuses a fixed number of threads operating off a shared
unbounded queue, using the provided ThreadFactory to create new threads when
needed.
CachedThreadPool
● It is unbounded thread pool, with automatic thread reclamation
Executors utility class have factory methods for creating CachedThreadPool:
1) static ExecutorService newCachedThreadPool()
Creates a thread pool that creates new threads as needed, but will reuse
previously constructed threads when they are available.
2) static ExecutorService newCachedThreadPool(ThreadFactory
threadFactory)
Creates a thread pool that creates new threads as needed, but will reuse
previously constructed threads when they are available, and uses the
provided ThreadFactory to create new threads when needed.
ForkJoinPool
● A ForkJoinPool is an ExecutorService that recognizes explicit dependencies between
tasks. It is designed for the kind of computation that wants to run in parallel, and then
maybe more parallel, and then some of those can run in parallel too. Results of the
parallel computations are then combined, so it's like the threads want to split off and
then regroup.
● A ForkJoinPool differs from other kinds of ExecutorService mainly by virtue of
employing work-stealing: all threads in the pool attempt to find and execute subtasks
created by other active tasks (eventually blocking waiting for work if none exist). This
enables efficient processing when most tasks spawn other subtasks (as do most
ForkJoinTasks). When setting asyncMode to true in constructors, ForkJoinPools may
also be appropriate for use with event-style tasks that are never joined.
Implementation notes: This implementation restricts the maximum number of
running threads to 32767. Attempts to create pools with greater than the maximum
number result in IllegalArgumentException.
ForkJoinPool
//Creates a ForkJoinPool with parallelism equal to Runtime.availableProcessors(),
using the default thread factory
val mainPool: ForkJoinPool = new ForkJoinPool()
//Creates a ForkJoinPool with the indicated parallelism level, the default thread
factory,
val mainPoolWithParallelism: ForkJoinPool = new ForkJoinPool(50)
Choosing-executorservice
http://blog.jessitron.com/2014/01/choosing-executorservice.html
Best practices
● How you should best divide work in your application between different thread
pools greatly depends on the types of work that your application is doing,
and the control you want to have over how much of which work can be done
in parallel.
● There is no one size fits all solution to the problem, and the best decision for
you will come from understanding the blocking-IO requirements of your
application and the implications they have on your thread pools. It may help
to do load testing on your application to tune and verify your configuration.
Best practices
object Contexts {
val noOfThreadForDBOperation = 10 // set according to application load
implicit val simpleDbLookups: ExecutionContext =
ExecutionContext.fromExecutor(Executors.newCachedThreadPool())
implicit val expensiveDbLookups: ExecutionContext =
ExecutionContext.fromExecutor(Executors.newFixedThreadPool(noOfThreadForDBOperation))
implicit val expensiveCpuOperations: ExecutionContext =
ExecutionContext.fromExecutor(new ForkJoinPool())
}
Play’s thread pools
Play2.3 uses a number of different thread pools for different purposes:
Netty boss/worker thread pools - These are used internally by Netty for handling Netty IO. An
applications code should never be executed by a thread in these thread pools.
Play Internal Thread Pool - This is used internally by Play. No application code should ever be executed
by a thread in this thread pool, and no blocking should ever be done in this thread pool. Its size can be
configured by setting internal-threadpool-size in application.conf, and it defaults to the number of available
processors.
Play default thread pool - This is the default thread pool in which all application code in Play Framework
is executed. It is an Akka dispatcher, and can be configured by configuring Akka. By default, it has one
thread per processor.
Akka thread pool - This is used by the Play Akka plugin, and can be configured the same way that you
would configure Akka.
Play’s thread pools
Play2.4 uses a number of different thread pools for different purposes:
Netty boss/worker thread pools - These are used internally by Netty for handling Netty IO. An
application’s code should never be executed by a thread in these thread pools.
Play default thread pool - This is the thread pool in which all of your application code in Play Framework
is executed. It is an Akka dispatcher, and is used by the application ActorSystem. It can be configured by
configuring Akka, described below.
Note that in Play 2.4 several thread pools were combined together into the Play default thread pool.
Play’s thread pools
In most situations, the appropriate execution context to use will be the Play default thread pool. This can
be used by importing it into your Scala source file:
//in play
import play.api.libs.concurrent.Execution.Implicits._
// in scala
import scala.concurrent.ExecutionContext.Implicits._
Best practices
object Contexts {
implicit val simpleDbLookups: ExecutionContext =
Akka.system.dispatchers.lookup("contexts.simple-db-lookups")
implicit val expensiveDbLookups: ExecutionContext =
Akka.system.dispatchers.lookup("contexts.expensive-db-lookups")
implicit val dbWriteOperations: ExecutionContext =
Akka.system.dispatchers.lookup("contexts.db-write-operations")
implicit val expensiveCpuOperations: ExecutionContext =
Akka.system.dispatchers.lookup("contexts.expensive-cpu-operations")
}
These might then be configured like so:
contexts {
simple-db-lookups {
fork-join-executor {
parallelism-factor = 10.0
}
}
expensive-db-lookups {
fork-join-executor {
parallelism-max = 4
}
}
db-write-operations {
fork-join-executor {
parallelism-factor = 2.0
}
}
expensive-cpu-operations {
fork-join-executor {
parallelism-max = 2
}
}
}
References
● Futures and Promises
● http://blog.jessitron.com/2014/01/choosing-executorservice.html
● http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ForkJo
● https://www.playframework.com/documentation/2.3.x/ThreadPools
● https://www.playframework.com/documentation/2.4.x/ThreadPools

More Related Content

PDF
Scalability, Availability & Stability Patterns
PDF
Kubernetes Forum Seoul 2019: Re-architecting Data Platform with Kubernetes
PDF
噛み砕いてKafka Streams #kafkajp
PPTX
Azure cosmos db, Azure no-SQL database,
PDF
Optimizing Kubernetes Resource Requests/Limits for Cost-Efficiency and Latenc...
PDF
Amazon ElastiCacheのはじめ方
PDF
Railsで作るBFFの功罪
PPTX
Introduction to Microservices
Scalability, Availability & Stability Patterns
Kubernetes Forum Seoul 2019: Re-architecting Data Platform with Kubernetes
噛み砕いてKafka Streams #kafkajp
Azure cosmos db, Azure no-SQL database,
Optimizing Kubernetes Resource Requests/Limits for Cost-Efficiency and Latenc...
Amazon ElastiCacheのはじめ方
Railsで作るBFFの功罪
Introduction to Microservices

What's hot (20)

PDF
[Gaming on AWS] AWS와 함께 한 쿠키런 서버 Re-architecting 사례 - 데브시스터즈
PDF
From Zero to Hero with Kafka Connect
PPTX
SKYDISCのIoTを支えるテクノロジー
PPTX
ビズリーチにおけるEMR(AWS)活用事例
PDF
Parallelizing with Apache Spark in Unexpected Ways
PPTX
Toi uu hoa he thong 30 trieu nguoi dung
PDF
Apache Kafka 0.11 の Exactly Once Semantics
PDF
The Best of Both Worlds: Introducing WSO2 API Manager 4.0.0
PDF
Growing the Delta Ecosystem to Rust and Python with Delta-RS
PDF
Microservices Tutorial for Beginners | Microservices Architecture | Microserv...
PDF
Apache Spark At Scale in the Cloud
PDF
Reactive Programming for a demanding world: building event-driven and respons...
PPTX
HBase Read High Availabilty using Timeline Consistent Region Replicas
PDF
Yahoo! JAPANのコンテンツプラットフォームを支えるSpring Cloud Streamによるマイクロサービスアーキテクチャ #jsug #sf_52
PPTX
/path/to/content - the Apache Jackrabbit content repository
PDF
데브시스터즈 데이터 레이크 구축 이야기 : Data Lake architecture case study (박주홍 데이터 분석 및 인프라 팀...
PDF
Testing Kafka containers with Testcontainers: There and back again with Vikto...
PDF
よろしい、ならばMicro-ORMだ
PDF
OpenTelemetry: From front- to backend (2022)
PPTX
Secret Management with Hashicorp Vault and Consul on Kubernetes
[Gaming on AWS] AWS와 함께 한 쿠키런 서버 Re-architecting 사례 - 데브시스터즈
From Zero to Hero with Kafka Connect
SKYDISCのIoTを支えるテクノロジー
ビズリーチにおけるEMR(AWS)活用事例
Parallelizing with Apache Spark in Unexpected Ways
Toi uu hoa he thong 30 trieu nguoi dung
Apache Kafka 0.11 の Exactly Once Semantics
The Best of Both Worlds: Introducing WSO2 API Manager 4.0.0
Growing the Delta Ecosystem to Rust and Python with Delta-RS
Microservices Tutorial for Beginners | Microservices Architecture | Microserv...
Apache Spark At Scale in the Cloud
Reactive Programming for a demanding world: building event-driven and respons...
HBase Read High Availabilty using Timeline Consistent Region Replicas
Yahoo! JAPANのコンテンツプラットフォームを支えるSpring Cloud Streamによるマイクロサービスアーキテクチャ #jsug #sf_52
/path/to/content - the Apache Jackrabbit content repository
데브시스터즈 데이터 레이크 구축 이야기 : Data Lake architecture case study (박주홍 데이터 분석 및 인프라 팀...
Testing Kafka containers with Testcontainers: There and back again with Vikto...
よろしい、ならばMicro-ORMだ
OpenTelemetry: From front- to backend (2022)
Secret Management with Hashicorp Vault and Consul on Kubernetes
Ad

Viewers also liked (6)

PDF
How does Scala's Future work?
PDF
Introduction to Asynchronous scala
PDF
Play Framework: async I/O with Java and Scala
PDF
Reactive Stream Processing with Akka Streams
PPT
Futures and options
PDF
Callbacks, promises, generators - asynchronous javascript
How does Scala's Future work?
Introduction to Asynchronous scala
Play Framework: async I/O with Java and Scala
Reactive Stream Processing with Akka Streams
Futures and options
Callbacks, promises, generators - asynchronous javascript
Ad

Similar to Scala Future & Promises (20)

PDF
Using Akka Futures
PDF
Codemotion akka voló sobre el nido del future
PDF
Codemotion 2015 - Akka voló sobre el nido del future
PPTX
PDF
Monix : A Birds’ eye view
PDF
Making our Future better
PPTX
Promise of a better future by Rahul Goma Phulore and Pooja Akshantal, Thought...
PDF
Completable future
PDF
Why scala is not my ideal language and what I can do with this
PDF
Principles of the Play framework
PPTX
play framework async with scala
PDF
Beyond Mere Actors
PDF
Pure Future
ODP
Concurrent Programming in Java
PDF
Scala(e) to the large. Concurrent programming in Scala and relevant Frameworks
PPTX
Completable Future java 8 Features with example
PDF
Back to the futures, actors and pipes: using Akka for large-scale data migration
PDF
The Future of Futures - A Talk About Java 8 CompletableFutures
PPTX
Async java8
ODP
CompletableFuture
Using Akka Futures
Codemotion akka voló sobre el nido del future
Codemotion 2015 - Akka voló sobre el nido del future
Monix : A Birds’ eye view
Making our Future better
Promise of a better future by Rahul Goma Phulore and Pooja Akshantal, Thought...
Completable future
Why scala is not my ideal language and what I can do with this
Principles of the Play framework
play framework async with scala
Beyond Mere Actors
Pure Future
Concurrent Programming in Java
Scala(e) to the large. Concurrent programming in Scala and relevant Frameworks
Completable Future java 8 Features with example
Back to the futures, actors and pipes: using Akka for large-scale data migration
The Future of Futures - A Talk About Java 8 CompletableFutures
Async java8
CompletableFuture

More from Knoldus Inc. (20)

PPTX
Angular Hydration Presentation (FrontEnd)
PPTX
Optimizing Test Execution: Heuristic Algorithm for Self-Healing
PPTX
Self-Healing Test Automation Framework - Healenium
PPTX
Kanban Metrics Presentation (Project Management)
PPTX
Java 17 features and implementation.pptx
PPTX
Chaos Mesh Introducing Chaos in Kubernetes
PPTX
GraalVM - A Step Ahead of JVM Presentation
PPTX
Nomad by HashiCorp Presentation (DevOps)
PPTX
Nomad by HashiCorp Presentation (DevOps)
PPTX
DAPR - Distributed Application Runtime Presentation
PPTX
Introduction to Azure Virtual WAN Presentation
PPTX
Introduction to Argo Rollouts Presentation
PPTX
Intro to Azure Container App Presentation
PPTX
Insights Unveiled Test Reporting and Observability Excellence
PPTX
Introduction to Splunk Presentation (DevOps)
PPTX
Code Camp - Data Profiling and Quality Analysis Framework
PPTX
AWS: Messaging Services in AWS Presentation
PPTX
Amazon Cognito: A Primer on Authentication and Authorization
PPTX
ZIO Http A Functional Approach to Scalable and Type-Safe Web Development
PPTX
Managing State & HTTP Requests In Ionic.
Angular Hydration Presentation (FrontEnd)
Optimizing Test Execution: Heuristic Algorithm for Self-Healing
Self-Healing Test Automation Framework - Healenium
Kanban Metrics Presentation (Project Management)
Java 17 features and implementation.pptx
Chaos Mesh Introducing Chaos in Kubernetes
GraalVM - A Step Ahead of JVM Presentation
Nomad by HashiCorp Presentation (DevOps)
Nomad by HashiCorp Presentation (DevOps)
DAPR - Distributed Application Runtime Presentation
Introduction to Azure Virtual WAN Presentation
Introduction to Argo Rollouts Presentation
Intro to Azure Container App Presentation
Insights Unveiled Test Reporting and Observability Excellence
Introduction to Splunk Presentation (DevOps)
Code Camp - Data Profiling and Quality Analysis Framework
AWS: Messaging Services in AWS Presentation
Amazon Cognito: A Primer on Authentication and Authorization
ZIO Http A Functional Approach to Scalable and Type-Safe Web Development
Managing State & HTTP Requests In Ionic.

Recently uploaded (20)

PPTX
ELIAS-SEZIURE AND EPilepsy semmioan session.pptx
PDF
CISA (Certified Information Systems Auditor) Domain-Wise Summary.pdf
PDF
Τίμαιος είναι φιλοσοφικός διάλογος του Πλάτωνα
PDF
Journal of Dental Science - UDMY (2022).pdf
PPTX
B.Sc. DS Unit 2 Software Engineering.pptx
PDF
Journal of Dental Science - UDMY (2020).pdf
PPTX
Module on health assessment of CHN. pptx
PPTX
Computer Architecture Input Output Memory.pptx
PDF
BP 505 T. PHARMACEUTICAL JURISPRUDENCE (UNIT 1).pdf
PDF
LEARNERS WITH ADDITIONAL NEEDS ProfEd Topic
PDF
IP : I ; Unit I : Preformulation Studies
PPTX
Unit 4 Computer Architecture Multicore Processor.pptx
PDF
LIFE & LIVING TRILOGY- PART (1) WHO ARE WE.pdf
PDF
semiconductor packaging in vlsi design fab
PDF
CRP102_SAGALASSOS_Final_Projects_2025.pdf
PDF
International_Financial_Reporting_Standa.pdf
PPTX
A powerpoint presentation on the Revised K-10 Science Shaping Paper
PDF
LIFE & LIVING TRILOGY - PART (3) REALITY & MYSTERY.pdf
PDF
HVAC Specification 2024 according to central public works department
PPTX
Education and Perspectives of Education.pptx
ELIAS-SEZIURE AND EPilepsy semmioan session.pptx
CISA (Certified Information Systems Auditor) Domain-Wise Summary.pdf
Τίμαιος είναι φιλοσοφικός διάλογος του Πλάτωνα
Journal of Dental Science - UDMY (2022).pdf
B.Sc. DS Unit 2 Software Engineering.pptx
Journal of Dental Science - UDMY (2020).pdf
Module on health assessment of CHN. pptx
Computer Architecture Input Output Memory.pptx
BP 505 T. PHARMACEUTICAL JURISPRUDENCE (UNIT 1).pdf
LEARNERS WITH ADDITIONAL NEEDS ProfEd Topic
IP : I ; Unit I : Preformulation Studies
Unit 4 Computer Architecture Multicore Processor.pptx
LIFE & LIVING TRILOGY- PART (1) WHO ARE WE.pdf
semiconductor packaging in vlsi design fab
CRP102_SAGALASSOS_Final_Projects_2025.pdf
International_Financial_Reporting_Standa.pdf
A powerpoint presentation on the Revised K-10 Science Shaping Paper
LIFE & LIVING TRILOGY - PART (3) REALITY & MYSTERY.pdf
HVAC Specification 2024 according to central public works department
Education and Perspectives of Education.pptx

Scala Future & Promises

  • 1. Asynchronous Programming with Future & Promises Asynchronous Programming with Future & Promises Satendra Kumar Software Consultant Knoldus Software LLP Satendra Kumar Software Consultant Knoldus Software LLP
  • 2. Topics CoveredTopics Covered Future Callback Handler Functional Composition For-Comprehension Blocking Future Promises Live Demo Executor Services Choosing-executor service Best practices Future Callback Handler Functional Composition For-Comprehension Blocking Future Promises Live Demo Executor Services Choosing-executor service Best practices
  • 3. import org.apache.commons.io.IOUtils import org.apache.http.client.methods.HttpGet import org.apache.http.impl.client.HttpClientBuilder object FacebookPage { private val homeURL = "https://graph.facebook.com/v2.0/" private val accessToken = "CAAVHCxa" private val url = s"$homeURL${"25"}/feed?method=GET&format=json&access_token=$ {accessToken}" def getFeeds(): String = { val request = new HttpGet(url) val client = HttpClientBuilder.create().build(); val response = client.execute(request) IOUtils.toString(response.getEntity().getContent()) } }
  • 4. object FacebookFeedParser { implicit val formats = DefaultFormats def parse(facebookFeeds: String): List[FacebookPageFeed] = { val parsedFacebookFeeds = net.liftweb.json.parse(facebookFeeds) (parsedFacebookFeeds "data").children map { facebookfeed => val contentId = (facebookfeed "id") val date = (facebookfeed "created_time") val content = (facebookfeed "message") FacebookPageFeed(contentId, date, content) } } implicit def extract(json: JValue): String = json match { case JNothing => "" case data => data.extract[String] } } case class FacebookPageFeed(id: String, date: String, content: String)
  • 5. object DemoApp extends App { val facebookFeeds = FacebookPage.getFeeds() val parsedFacebookFeed = FacebookFeedParser.parse(facebookFeeds) val result = FacebookRepository.save(parsedFacebookFeed) // do some other tasks }
  • 6. object DemoApp extends App { val facebookFeeds = FacebookPage.getFeeds() val parsedFacebookFeed = FacebookFeedParser.parse(facebookFeeds) val result = FacebookRepository.save(parsedFacebookFeed) // do some other tasks } Something wrong ?
  • 7. object DemoApp extends App { val facebookFeeds = FacebookPage.getFeeds() val parsedFacebookFeed = FacebookFeedParser.parse(facebookFeeds) val result = FacebookRepository.save(parsedFacebookFeed) // do some other tasks } This is blocking
  • 9. Scala's Futures API ➢ Futures provide a nice way to reason about performing many operations in parallel– in an efficient and non-blocking way.
  • 10. Scala's Futures API ➢ Futures provide a nice way to reason about performing many operations in parallel– in an efficient and non-blocking way. ➢ The idea is simple, a Future is a sort of a placeholder object that you can create for a result that does not yet exist. Generally, the result of the Future is computed concurrently and can be later collected. Composing concurrent tasks in this way tends to result in faster, asynchronous, non-blocking parallel code.
  • 11. Scala's Futures API ➢ Futures provide a nice way to reason about performing many operations in parallel– in an efficient and non-blocking way. ➢ The idea is simple, a Future is a sort of a placeholder object that you can create for a result that does not yet exist. Generally, the result of the Future is computed concurrently and can be later collected. Composing concurrent tasks in this way tends to result in faster, asynchronous, non-blocking parallel code. ➢ By default, futures and promises are non-blocking, making use of callbacks instead of typical blocking operations.
  • 12. Scala's Futures API ➢ Futures provide a nice way to reason about performing many operations in parallel– in an efficient and non-blocking way. ➢ The idea is simple, a Future is a sort of a placeholder object that you can create for a result that does not yet exist. Generally, the result of the Future is computed concurrently and can be later collected. Composing concurrent tasks in this way tends to result in faster, asynchronous, non-blocking parallel code. ➢ By default, futures and promises are non-blocking, making use of callbacks instead of typical blocking operations. ➢ Blocking is still possible - for cases where it is absolutely necessary, futures can be blocked on (although this is discouraged).
  • 13. import scala.concurrent.Future import scala.concurrent.ExecutionContext.Implicits.global import com.knol.facebook.FacebookPage object DemoApp extends App { val facebookFeeds: Future[String] = Future { FacebookPage.getFeeds() } }
  • 14. def apply[T](body: =>T)(implicit executor: ExecutionContext): Future[T] Future's apply method
  • 15. Implicit Execution Context object Implicits { implicit lazy val global: ExecutionContextExecutor = impl.ExecutionContextImpl.fromExecutor(null: Executor) }
  • 16. Explicit Execution Context ➢ We can specify own ExecutionContext , instead of importing the global implicit ExecutionContext. import java.util.concurrent.Executors import scala.concurrent.ExecutionContext import scala.concurrent.Future import com.knol.facebook.FacebookPage import scala.concurrent.ExecutionContextExecutor import java.util.concurrent.ExecutorService object DemoApp extends App { val noOfThread = 10 val threadPool:ExecutorService = Executors.newFixedThreadPool(noOfThread) val ec: ExecutionContextExecutor = ExecutionContext.fromExecutor(threadPool) val facebookFeeds = Future { FacebookPage.getFeeds() }(ec) }
  • 17. import scala.concurrent.Future import scala.concurrent.ExecutionContext.Implicits.global import com.knol.facebook.FacebookPage object DemoApp extends App { val facebookFeeds: Future[String] = Future { FacebookPage.getFeeds() } } Future completion can take one of two forms:
  • 18. import scala.concurrent.Future import scala.concurrent.ExecutionContext.Implicits.global import com.knol.facebook.FacebookPage object DemoApp extends App { val facebookFeeds: Future[String] = Future { FacebookPage.getFeeds() } } Future completion can take one of two forms: a)When a Future is completed with a value, we say that the future was successfully completed with that value.
  • 19. import scala.concurrent.Future import scala.concurrent.ExecutionContext.Implicits.global import com.knol.facebook.FacebookPage object DemoApp extends App { val facebookFeeds: Future[String] = Future { FacebookPage.getFeeds() } } Future completion can take one of two forms: a)When a Future is completed with a value, we say that the future was successfully completed with that value. b)When a Future is completed with an exception thrown by the computation, we say that the Future was failed with that exception.
  • 21. Callbacks ➢ We now know how to start an asynchronous computation to create a new future value, but we have not shown how to use the result once it becomes available, so that we can do something useful with it.
  • 22. Callbacks ➢ We now know how to start an asynchronous computation to create a new future value, but we have not shown how to use the result once it becomes available, so that we can do something useful with it. ➢ We can get result by registering a callback on the future.
  • 23. Callbacks ➢ We now know how to start an asynchronous computation to create a new future value, but we have not shown how to use the result once it becomes available, so that we can do something useful with it. ➢ We can get result by registering a callback on the future. ➢ This callback is called asynchronously once the future is completed. If the future has already been completed when registering the callback, then the callback may either be executed asynchronously, or sequentially on the same thread.
  • 24. Callbacks def onSuccess[U](pf: PartialFunction[T, U])(implicit executor:ExecutionContext): Unit def onFailure[U](pf:PartialFunction[Throwable,U])(implicit executor:ExecutionContext): Unit def onComplete[U](f: Try[T] => U)(implicit executor: ExecutionContext): Unit
  • 25. import scala.concurrent.Future import scala.concurrent.ExecutionContext.Implicits.global import com.knol.facebook.FacebookPage object DemoApp extends App { val facebookFeeds: Future[String] = Future { FacebookPage.getFeeds() } facebookFeeds onSuccess { case feeds => println(feeds) } } onSuccess
  • 26. onFailure object DemoApp extends App { val facebookFeeds: Future[String] = Future { FacebookPage.getFeeds() } facebookFeeds onFailure { case feeds:Throwable => println("Error getting feeds "+feeds.getMessage) } }
  • 27. onComplete import scala.concurrent.Future import scala.concurrent.ExecutionContext.Implicits.global import com.knol.facebook.FacebookPage import scala.util.Success import scala.util.Failure object DemoApp extends App { val facebookFeeds: Future[String] = Future { FacebookPages.getFeeds() } facebookFeeds onComplete { case Success(feeds) => println("feeds " + feeds) case Failure(ex) => println("Error "+ex.getMessage) } }
  • 28. Callbacks ➢ Callbacks registered on the same future are unordered. ➢ There is no guarantee it will be called by the thread that completed the future or the thread which created the callback. Instead, the callback is executed by some thread, at some time after the future object is completed. ➢ Registering a callback on the future which is already completed will result in the callback being executed eventually. ➢ Once executed, the callbacks are removed from the future object, thus being eligible for GC
  • 29. Functional Composition Futures provide combinators which allow a more straightforward composition. def map[S](f: T => S)(implicit executor: ExecutionContext): Future[S] def flatMap[S](f: T => Future[S])(implicit executor: ExecutionContext): Future[S] def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit ec: ExecutionContext): Future[U] def recoverWith[U >: T](pf: PartialFunction[Throwable,Future[U]])(implicit ec: ExecutionContext):Future[U] def foreach[U](f: T => U)(implicit executor: ExecutionContext): Unit def fallbackTo[U >: T](that: Future[U]): Future[U] def andThen[U](pf: PartialFunction[Try[T], U])(implicit executor: ExecutionContext): Future[T] def mapTo[S](implicit tag: ClassTag[S]): Future[S] def sequence[A, M[X] <: TraversableOnce[X]](in: M[Future[A]])( implicit cbf: CanBuildFrom[M[Future[A]], A, M[A]], executor: ExecutionContext): Future[M[A]]
  • 30. map import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scala.util.Failure import scala.util.Success import com.knol.facebook.FacebookPage import com.knol.facebook.FacebookFeedParser import com.knol.facebook.FacebookPageFeed object DemoApp extends App { val facebookFeeds: Future[String] = Future { FacebookPage.getFeeds() } val feedList: Future[List[FacebookPageFeed]] = facebookFeeds map { feed => FacebookFeedParser.parse(feed) } feedList onComplete { case Success(feeds) => feeds foreach println case Failure(ex) => println("Error getting feed " + ex.getMessage) } }
  • 31. flatMap import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scala.util.Failure import scala.util.Success import com.knol.facebook.FacebookPage import com.knol.facebook.FacebookFeedParser import com.knol.facebook.FacebookPageFeed object DemoApp extends App { val facebookFeeds: Future[String] = Future { FacebookPage.getFeeds() } val feedList: Future[List[FacebookPageFeed]] = facebookFeeds flatMap { feed => FacebookFeedParser.parse(feed) } feedList onComplete { case Success(feeds) => feeds foreach println case Failure(ex) => println("Error getting feed " + ex.getMessage) } }
  • 32. foreach import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scala.util.Failure import scala.util.Success import com.knol.facebook.FacebookPage import com.knol.facebook.FacebookFeedParser import com.knol.facebook.FacebookPageFeed object DemoApp extends App { val facebookFeeds: Future[String] = Future { FacebookPage.getFeeds() } val feedList: Future[List[FacebookPageFeed]] = facebookFeeds flatMap { feed => FacebookFeedParser.parse(feed) } feedList foreach println }
  • 33. recover import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scala.util.Failure import scala.util.Success import com.knol.facebook.FacebookPage import com.knol.facebook.FacebookFeedParser import com.knol.facebook.FacebookPageFeed object DemoApp extends App { val facebookFeeds: Future[String] = Future { FacebookPage.getFeeds() } val feedList: Future[List[FacebookPageFeed]] = facebookFeeds map { feed => FacebookFeedParser.parse(feed) } recover { case ex: Throwable => List() } feedList onComplete { case Success(feeds) => feeds foreach println case Failure(ex) => println("Error getting feed " + ex.getMessage) } }
  • 34. recoverWith import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scala.util.Failure import scala.util.Success import com.knol.facebook.FacebookPage import com.knol.facebook.FacebookFeedParser import com.knol.facebook.FacebookPageFeed object DemoApp extends App { val facebookFeeds: Future[String] = Future { FacebookPage.getFeeds() } val feedList: Future[List[FacebookPageFeed]] = facebookFeeds flatMap { feed => FacebookFeedParser.parse(feed) } recoverWith { case ex: Throwable => Future { List(FacebookPageFeed("", "", "")) } } feedList onComplete { case Success(feeds) => feeds foreach println case Failure(ex) => println("Error getting feed " + ex.getMessage) } }
  • 35. fallbackTo import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scala.util.Failure import scala.util.Success import com.knol.facebook.FacebookPage import com.knol.facebook.FacebookFeedParser import com.knol.facebook.FacebookPageFeed object DemoApp extends App { val facebookFeeds: Future[String] = Future { FacebookPage.getFeeds() } val fallbackFuture: Future[String] = Future { "{}" } val resultantFuture = facebookFeeds fallbackTo fallbackFuture resultantFuture onComplete { case Success(feeds) => feeds foreach println case Failure(ex) => println("Error getting feed " + ex.getMessage) } }
  • 36. andThen The andThen combinator is used purely for side-effecting purposes. It returns a new future with exactly the same result as the current future, regardless of whether the current future failed or not. Once the current future is completed with the result, the closure corresponding to the andThen is invoked and then the new future is completed with the same result as this future import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scala.util._ import com.knol.facebook.FacebookPage import com.knol.facebook.FacebookFeedParser object DemoApp extends App { val facebookFeeds: Future[String] = Future { FacebookPage.getFeeds() } val resultantFuture = facebookFeeds andThen { case Success(feed) => FacebookFeedParser.parse(feed) foreach println } resultantFuture onComplete { case Success(feeds) => feeds foreach println case Failure(ex) => println("Error getting feed " + ex.getMessage) } }
  • 37. sequence val listOfFuture: List[Future[Int]] = List(Future(2 + 2), Future(20 + 3), Future(2 + 347)) val combindFuture: Future[List[Int]] = Future.sequence(listOfFuture)
  • 38. For-Comprehensions import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import com.knol.facebook.FacebookPage import com.knol.facebook.FacebookFeedParser import com.knol.facebook.FacebookPageFeed import scala.concurrent.Await import scala.concurrent.duration._ import scala.util.Success import scala.util.Failure object DemoApp extends App { val facebookFeeds: Future[String] = Future { println("Current Thread in future block::::::" + Thread.currentThread().getName) FacebookPage.getFeeds() } val future = for { feeds <- facebookFeeds parsedFeed <- Future(FacebookFeedParser.parse(feeds)) } yield parsedFeed future onComplete { case Success(feeds) => println("Feeds:::::::::::" + feeds) case Failure(ex) => println("Error:::::::::::" + ex.getMessage) } }
  • 39. Blocking ● blocking on a future is strongly discouraged for the sake of performance and for the prevention of deadlocks. Callbacks and combinators on futures are a preferred way to use their results. However, blocking may be necessary in certain situations and is supported by the Futures and Promises API. import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import com.knol.facebook.FacebookPage import com.knol.facebook.FacebookFeedParser import com.knol.facebook.FacebookPageFeed import scala.concurrent.Await import scala.concurrent.duration._ object DemoApp extends App { val facebookFeeds: Future[String] = Future { FacebookPage.getFeeds() } val result = Await.result(facebookFeeds, 10 seconds) println(result) }
  • 41. Promises ➢ Promise is an object which can be completed with a value or failed with an exception.
  • 42. Promises ➢ Promise is an object which can be completed with a value or failed with an exception. ➢ While futures are defined as a type of read-only placeholder object created for a result which doesn’t yet exist, a promise can be thought of as a writable, single-assignment container, which completes a future. That is, a promise can be used to successfully complete a future with a value (by “completing” the promise) using the success method. Conversely, a promise can also be used to complete a future with an exception, by failing the promise, using the failure method.
  • 43. Promises ➢ Promise is an object which can be completed with a value or failed with an exception. ➢ While futures are defined as a type of read-only placeholder object created for a result which doesn’t yet exist, a promise can be thought of as a writable, single-assignment container, which completes a future. That is, a promise can be used to successfully complete a future with a value (by “completing” the promise) using the success method. Conversely, a promise can also be used to complete a future with an exception, by failing the promise, using the failure method. ➢ A promise p completes the future returned by p.future. This future is specific to the promise p. Depending on the implementation, it may be the case that p.future eq p.
  • 44. import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import com.knol.facebook.FacebookPage import scala.concurrent.duration._ import scala.util.Success import scala.util.Failure import scala.concurrent.Promise object PromiseDemo extends App { val promise = Promise[String] val future = promise.future Future { val feeds = FacebookPage.getFeeds() promise success feeds } future onComplete { case Success(feeds) => println("Feeds:::::::::::" + feeds) case Failure(ex) => println("Error:::::::::::" + ex.getMessage) } }
  • 45. import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scala.concurrent.Promise import com.knol.facebook.FacebookPage object PromiseDemo { def asynExecute: Future[String] = { val promise = Promise[String] Future { //do other task val feeds = FacebookPage.getFeeds() promise success feeds //do other task } promise.future } }
  • 46. 1) Write a method that return a future that is never completed
  • 47. 1) Write a method that return a future that is never completed def never[T]: Future[T] = Promise[T].future
  • 48. 1) Write a method that return a future that is never completed def never[T]: Future[T] = Promise[T].future 2) Write a method that return a future with a unit value that is completed after time `t`
  • 49. 1) Write a method that return a future that is never completed def never[T]: Future[T] = Promise[T].future 2) Write a method that return a future with a unit value that is completed after time `t` def delay(t: Duration): Future[Unit] = Future { Try(Await.ready(Promise().future, t)) }
  • 50. Executor Services ● FixedThreadPool ● CachedThreadPool ● SingleThreadExecutor ● ForkJoinPool
  • 51. FixedThreadPool ● It is fixed size thread pool Executors utility class have factory methods for creating FixedThreadPool: 1) static ExecutorService newFixedThreadPool(int nThreads) Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue. 2) static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue, using the provided ThreadFactory to create new threads when needed.
  • 52. CachedThreadPool ● It is unbounded thread pool, with automatic thread reclamation Executors utility class have factory methods for creating CachedThreadPool: 1) static ExecutorService newCachedThreadPool() Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available. 2) static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available, and uses the provided ThreadFactory to create new threads when needed.
  • 53. ForkJoinPool ● A ForkJoinPool is an ExecutorService that recognizes explicit dependencies between tasks. It is designed for the kind of computation that wants to run in parallel, and then maybe more parallel, and then some of those can run in parallel too. Results of the parallel computations are then combined, so it's like the threads want to split off and then regroup. ● A ForkJoinPool differs from other kinds of ExecutorService mainly by virtue of employing work-stealing: all threads in the pool attempt to find and execute subtasks created by other active tasks (eventually blocking waiting for work if none exist). This enables efficient processing when most tasks spawn other subtasks (as do most ForkJoinTasks). When setting asyncMode to true in constructors, ForkJoinPools may also be appropriate for use with event-style tasks that are never joined. Implementation notes: This implementation restricts the maximum number of running threads to 32767. Attempts to create pools with greater than the maximum number result in IllegalArgumentException.
  • 54. ForkJoinPool //Creates a ForkJoinPool with parallelism equal to Runtime.availableProcessors(), using the default thread factory val mainPool: ForkJoinPool = new ForkJoinPool() //Creates a ForkJoinPool with the indicated parallelism level, the default thread factory, val mainPoolWithParallelism: ForkJoinPool = new ForkJoinPool(50)
  • 56. Best practices ● How you should best divide work in your application between different thread pools greatly depends on the types of work that your application is doing, and the control you want to have over how much of which work can be done in parallel. ● There is no one size fits all solution to the problem, and the best decision for you will come from understanding the blocking-IO requirements of your application and the implications they have on your thread pools. It may help to do load testing on your application to tune and verify your configuration.
  • 57. Best practices object Contexts { val noOfThreadForDBOperation = 10 // set according to application load implicit val simpleDbLookups: ExecutionContext = ExecutionContext.fromExecutor(Executors.newCachedThreadPool()) implicit val expensiveDbLookups: ExecutionContext = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(noOfThreadForDBOperation)) implicit val expensiveCpuOperations: ExecutionContext = ExecutionContext.fromExecutor(new ForkJoinPool()) }
  • 58. Play’s thread pools Play2.3 uses a number of different thread pools for different purposes: Netty boss/worker thread pools - These are used internally by Netty for handling Netty IO. An applications code should never be executed by a thread in these thread pools. Play Internal Thread Pool - This is used internally by Play. No application code should ever be executed by a thread in this thread pool, and no blocking should ever be done in this thread pool. Its size can be configured by setting internal-threadpool-size in application.conf, and it defaults to the number of available processors. Play default thread pool - This is the default thread pool in which all application code in Play Framework is executed. It is an Akka dispatcher, and can be configured by configuring Akka. By default, it has one thread per processor. Akka thread pool - This is used by the Play Akka plugin, and can be configured the same way that you would configure Akka.
  • 59. Play’s thread pools Play2.4 uses a number of different thread pools for different purposes: Netty boss/worker thread pools - These are used internally by Netty for handling Netty IO. An application’s code should never be executed by a thread in these thread pools. Play default thread pool - This is the thread pool in which all of your application code in Play Framework is executed. It is an Akka dispatcher, and is used by the application ActorSystem. It can be configured by configuring Akka, described below. Note that in Play 2.4 several thread pools were combined together into the Play default thread pool.
  • 60. Play’s thread pools In most situations, the appropriate execution context to use will be the Play default thread pool. This can be used by importing it into your Scala source file: //in play import play.api.libs.concurrent.Execution.Implicits._ // in scala import scala.concurrent.ExecutionContext.Implicits._
  • 61. Best practices object Contexts { implicit val simpleDbLookups: ExecutionContext = Akka.system.dispatchers.lookup("contexts.simple-db-lookups") implicit val expensiveDbLookups: ExecutionContext = Akka.system.dispatchers.lookup("contexts.expensive-db-lookups") implicit val dbWriteOperations: ExecutionContext = Akka.system.dispatchers.lookup("contexts.db-write-operations") implicit val expensiveCpuOperations: ExecutionContext = Akka.system.dispatchers.lookup("contexts.expensive-cpu-operations") } These might then be configured like so: contexts { simple-db-lookups { fork-join-executor { parallelism-factor = 10.0 } } expensive-db-lookups { fork-join-executor { parallelism-max = 4 } } db-write-operations { fork-join-executor { parallelism-factor = 2.0 } } expensive-cpu-operations { fork-join-executor { parallelism-max = 2 } } }
  • 62. References ● Futures and Promises ● http://blog.jessitron.com/2014/01/choosing-executorservice.html ● http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ForkJo ● https://www.playframework.com/documentation/2.3.x/ThreadPools ● https://www.playframework.com/documentation/2.4.x/ThreadPools