Does a Future get a new thread? - scala

Does a future implemented like below get a new thread? Apparently it is not(see the output below). Why? What should I do if I want my code to run on a new thread?
package MyTest
import com.twitter.util._
import scala.language.postfixOps
object Test {
def test1 = Future {
println("BeforeTest", Thread.currentThread())
Thread.sleep(5000)
println("AfterTest", Thread.currentThread())
}
def test2 = test1 onSuccess { case _ => println("Future on success") }
def main(args: Array[String]): Unit = {
println("main", Thread.currentThread())
test2
println("main123", Thread.currentThread())
}
}
Output:
(main,Thread[run-main-0,5,run-main-group-0])
(BeforeTest,Thread[run-main-0,5,run-main-group-0])
(AfterTest,Thread[run-main-0,5,run-main-group-0])
Future on success
(main123,Thread[run-main-0,5,run-main-group-0])

You are using twitter futures, not scala futures.
Twitter futures are not multithreaded by default.
You have to use a FuturePool (passing it an ExecutorService with your threadpool of choice)
Non-tested example (simple enough to work I hope :) ):
val executor = Executors.newFixedThreadPool(4)
val pool = FuturePool(executor)
def test1 = pool {
println("BeforeTest", Thread.currentThread())
Thread.sleep(5000)
println("AfterTest", Thread.currentThread())
}
def test2 = test1 onSuccess { case _ => println("Future on success") }
def main(args: Array[String]): Unit = {
println("main", Thread.currentThread())
test2
println("main123", Thread.currentThread())
executor.shutdown()
}

One of the interesting points of Futures is that you don't have to handle threads yourself. How they are executed depends entirely on the implicit ExecutionContext that is passed to the Future.apply() method (and other methods like map, flatMap, filter, etc.). A very gross implementation could create a new thread for each future being computed, but what mostly happens is that such code is executed by a pool of worker threads on the JVM.

Related

Why my Scala Async test never completes when I do Await.result?

I have created a simple test scenario that shows this:
class Test extends AsyncFunSuite {
test("async test") {
val f = Future {
val thread = new Thread {
override def run(): Unit = {
println("OKAYY")
}
}
thread.start()
}
Await.result(f, Duration.Inf)
Future {
assert(true)
}
}
}
When executing this, the test runs forever and never completes.
You will see the same behavior with all asynchronous testing in ScalaTest (AsyncFeatureSpec, AsyncFlatSpec, AsyncFreeSpec, AsyncFunSpec, AsyncFunSuite, AsyncWordSpec).
The reason for this is that the default execution context in ScalaTest is serial execution context. You can read more about this here: https://www.scalatest.org/user_guide/async_testing. I have summarized the important points below.
Using ScalaTest's serial execution context on the JVM will ensure the same thread that produced the Future[Assertion] returned from a test body is also used to execute any tasks given to the execution context while executing the test body—and that thread will not be allowed to do anything else until the test completes.
This thread confinement strategy does mean, however, that when you are using the default execution context on the JVM, you must be sure to never block in the test body waiting for a task to be completed by the execution context. If you block, your test will never complete.
Solution 1: Override execution context
implicit override def executionContext = scala.concurrent.ExecutionContext.Implicits.global
Solution 2: Chaining
class Test extends AsyncFunSuite {
test("async test") {
val f = Future {
val thread = new Thread {
override def run(): Unit = {
println("OKAYY")
}
}
thread.start()
}
f.map { _ =>
assert(true)
}
}
}

Nested Future.sequence executes included Futures sequentially

I have a future(doFour) that is executed and results passed to a flatmap.
Inside the flatmap I execute two more future(doOne and doTwo) functions expecting them to run on parallel but I see they are running sequentially (2.13). Scastie
Why are doOne and doTwo not execute in parallel ?
How can I have them to run in parallel ?
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future}
object Test {
def doOne(): Future[Unit] = Future {
println("startFirst"); Thread.sleep(3000); println("stopFirst")
}
def doTwo(): Future[Unit] = Future {
println("startSecond"); Thread.sleep(1000); println("stopSecond")
}
def doFour(): Future[Unit] = Future {
println("do 4"); Thread.sleep(1000); println("done 4")
}
def main(args: Array[String]) {
val resOut = doFour().flatMap { a =>
val futureOperations = Seq(doOne(), doTwo())
val res = Future.sequence(futureOperations)
res
}
val stream = Await.result(resOut, Duration.Inf)
}
}
A Future becomes eligible for execution as soon as it is created. So this line creates two Futures that can potentially be executed:
val futureOperations = Seq(doOne(), doTwo())
The call to Future.sequence will create a new Future that waits for each of the futures to complete in turn, but they will both already be available for execution by this point in the code.
val res = Future.sequence(futureOperations)
If you want Futures to start sequentially you need to use map/flatMap:
val res = doOne().map( _ => doTwo())
With this code doTwo will not be called until doOne completes (and not at all if doOne fails)
The reason that this does not appear to happen in your example is that you are calling a blocking operation in your Future which is blocking a thread that would otherwise be used to execute other Futures. So although there are two Futures available for execution, only one is actually being executed at a time.
If you mark the code as blocking it works correctly:
import scala.concurrent.blocking
def doOne(): Future[Unit] = Future {
blocking{println("startFirst"); Thread.sleep(3000); println("stop First")}
}
def doTwo(): Future[Unit] = Future {
blocking{println("startSecond"); Thread.sleep(1000); println("stop Second")}
}
See the comments section for details of why the default behaviour is different on different versions, and why you should never make assumptions about the relative execution order of independent Futures.

Scala future app terminates before complete

Just trying to get my first futures use up and running and doing a test similar to an example outlined in the Akka in Action MEAP book. I want to call a web service and return the result in a future. I am using scalaxb to access the web service. I have outlined the code below but when I run it the app terminates without waiting for the response from the service. Maybe someone can tell me what I am missing?
import scala.util._
import control.NonFatal
import scala.concurrent._
import ExecutionContext.Implicits.global
object Test {
val service = (new MyServiceBindings with scalaxb.Soap11Clients with scalaxb.DispatchHttpClients {}).service
def test = {
val f = future {
service.someCall() match {
case Right(resp) => resp
case Left(fault) => throw new Exception("Fault: " + fault)}
}
}
f.onComplete {
case Success(resp) => println("Resp: " + resp)
case Failure(NonFatal(e)) => println("Fail: " + e)
}
}
def main(args: Array[String]): Unit = {
test
}
}
It terminates because the main thread that is executed inside your Test has completed. The threads that are used internally by the Dispatch library don't keep the program from exiting.
You would need to wait on the future since this is the only thing your test app is doing. Put this after the onComplete statement.
import scala.concurrent.duration._
Await.ready(f, 10.seconds)
Now bear in mind that this is bad practice usually. You need it here because your test app is doing nothing else, but in a real app, you wouldn't want to block after each futures call, as that would negate the point of using futures.
You can patch this in the main funtion by adding the following logic to your test application:
def main(args: Array[String]) : Unit = {
// Assuming test is a future that did not complete yet.
while(!test.isCompleted) {
Thread.sleep(100)
}
// Software exits here only after future is completed.
}
Or Better if you have many futures you can implement it this way:
// Assuming you have --> listOfFutures = ArrayBuffer[Future]
def main(args: Array[String]) : Unit = {
while(!listOfFutures.isEmpty) {
listOfFutures.foreach {
future =>
if(future.isCompleted) {
listOfFutures -= future
}
}
//checks which futures are completed every half-a-second
Thread.sleep(500)
}
// Program exits after all futures have been completed.
}

In twitter future, how to set function of asynchronize return directly

I am new to future modern, what I expect from the following code is :
launch future task finished!
end of task
but actualy, the "end of task" appear first.
I want the process in function long_task to run asynchronizely.
what did I missed?
import com.twitter.util.Future
object FutureTest extends App{
def long_task(): Future[_] = { //the function of asynchronize processing
Thread.sleep(5000)
println("end of task")
Future.value("")
}
val f = long_task()
println("launch future task finished!")
}
The problem you are encountering is that long_task is a synchronous function that returns a completed future after it has done all the work. A future in and of itself does not start asynchronous work, but is just a handle for notification of asynchronous. It's still up to you to start the work asynchronously.
For your example using a FutureTask with a java ExecutorService will do the trick:
object FutureTest extends App{
val pool: ExecutorService = Executors.newFixedThreadPool(10)
def long_task(): Future[Unit] = {
// create a FutureTask, which is a Callable wrapped by a Future
val f = new FutureTask[Unit](new Callable[Unit]() {
def call(): Unit = {
Thread.sleep(5000)
println("end of task")
}})
// execute the callable
pool.execute(f)
// return the uncompleted future
f
}
val f = long_task()
println("launch future task finished!")
}
If you can use the scala Future instead of Twitter's the syntax gets a little simpler, since they've abstracted the underlying Threadpool work a bit further:
import scala.concurrent.ExecutionContext.Implicits._
import scala.concurrent.{Await, future}
import scala.concurrent.duration._
object FutureTest extends App {
def long_task() = future {
Thread.sleep(5000)
println("end of task")
}
val f = long_task()
println("launch future task finished!")
Await.result(f,10.seconds)
}
Note the Await at the end, which is needed here because with scala's default executorservice, the future work is a daemon thread which will not keep the runtime from quiting as soon as it reaches the last line. Await forces the program to block until the future completes.
Try it this way (create the Future first and execute):
import com.twitter.util.{Future, FutureTask}
object FutureTest extends App{
def long_task(): Future[_] = new FutureTask { //the function of asynchronize processing
Thread.sleep(5000)
println("end of task")
""
}
val f = long_task()
println("launch future task finished!")
}

Kill or timeout a Future in Scala 2.10

Hi,
I'm using Scala 2.10 with the new futures library and I'm trying to write some code to test an infinite loop. I use a scala.concurrent.Future to run the code with the loop in a separate thread. I would then like to wait a little while to do some testing and then kill off the separate thread/future. I have looked at Await.result but that doesn't actually kill the future. Is there any way to timeout or kill the new Scala 2.10 futures?
I would prefer not having to add external dependencies such as Akka just for this simple part.
Do not try it at home.
import scala.concurrent._
import scala.concurrent.duration._
class MyCustomExecutionContext extends AnyRef with ExecutionContext {
import ExecutionContext.Implicits.global
#volatile var lastThread: Option[Thread] = None
override def execute(runnable: Runnable): Unit = {
ExecutionContext.Implicits.global.execute(new Runnable() {
override def run() {
lastThread = Some(Thread.currentThread)
runnable.run()
}
})
}
override def reportFailure(t: Throwable): Unit = ???
}
implicit val exec = new MyCustomExecutionContext()
val f = future[Int]{ do{}while(true); 1 }
try {
Await.result(f, 10 seconds) // 100% cpu here
} catch {
case e: TimeoutException =>
println("Stopping...")
exec.lastThread.getOrElse(throw new RuntimeException("Not started"))
.stop() // 0% cpu here
}
No - you will have to add a flag that your loop checks. If the flag is set, stop the loop. Make sure the flag is at least volatile.
See Java Concurrency in Practice, p 135-137.
I had a similar problem and wrote the following nonblocking future op:
class TerminationToken(var isTerminated: Boolean)
object TerminationToken { def apply() = new TerminationToken(false) }
implicit class FutureOps[T](future: Future[Option[T]]) {
def terminate(timeout: FiniteDuration, token: TerminationToken): Future[Option[T]] = {
val timeoutFuture = after[Option[T]](timeout, using = context.system.scheduler) {
Future[Option[T]] { token.isTerminated = true; None } }
Future.firstCompletedOf[Option[T]](Seq (future recover { case _ => None }, timeoutFuture))
}
}
Then just create a future that returns an option, and use .terminate(timeout, token) on it