why the main app doesn't exit when calling a timer.schedule - scala

In the following,it run a calcuation after delay 2 seconds, but when run the app, it never exit. What is the code blocking the app to exit?
object Test extends App{
import scala.concurrent._
import java.util._
import java.util.concurrent.{ TimeUnit }
val timer = new java.util.Timer()
def timeoutFuture[A](v: A, delay: Long, unit: TimeUnit): Future[A] = {
println("inner")
val p = Promise[A]()
println("inner")
timer.schedule(new java.util.TimerTask {
def run() {
p.success(v)
}
}, unit.toMillis(delay))
println("inner")
p.future
}
println("begin")
val x1=timeoutFuture[Int](1+1,2,TimeUnit.SECONDS)
println("end")
println("quit")
}

val timer = new java.util.Timer() will start a TimerThread (which extends a standard Java thread and is implemented as an infinite loop), which is running in the background and prevent your application from exiting.
You can run System.exit(0) at the end of your script to stop all the background threads.
Also have you considered using Akka scheduler instead of Java Timer?

Related

Scala Concurrency: main thread lag

When I start some Scala Futures that perform expensive computations, the main thread starts to lag very badly. I don't use any callbacks just plain:
//got global execution context
for(i <- 0 until NUMBER_OF_FUTURES){
Future{do_work()}
}
What causes the freezes ?
EDIT:
Maybe execution context allows to run Futures on the main thread ?
EDIT2
Execution context I'm using:
private implicit val ec = new ExecutionContext
{
val threadPool = Executors.newSingleThreadExecutor()
def execute(runnable: Runnable) {
threadPool.submit(runnable)
}
def reportFailure(t: Throwable) {}
}

Executing More than 3 Futures does not work

I m using dispatch library in my sbt project. When I initialize three future and run them it is working perfectly But I increase one more future then it goes to a loop.
My code:
//Initializing Futures
def sequenceOfFutures() ={
var pageNumber: Int = 1
var list ={Seq(Future{})}
for (pageNumber <- 1 to 4) {
list ++= {
Seq(
Future {
str= getRequestFunction(pageNumber);
GlobalObjects.sleep(Random.nextInt(1500));
}
)
}
}
Future.sequence(list)
}
Await.result(sequenceOfFutures, Duration.Inf)
And then getRequestionFunction(pageNumber) code:
def getRequestionFunction(pageNumber)={
val h=Http("scala.org", as_str)
while(h.isComplete){
Thread,sleep(1500);
}
}
I tried based on one suggestion from How to configure a fine tuned thread pool for futures?
I added this to my code:
import java.util.concurrent.Executors
import scala.concurrent._
implicit val ec = new ExecutionContext {
val threadPool = Executors.newFixedThreadPool(1000);
def execute(runnable: Runnable) {
threadPool.submit(runnable)
}
def reportFailure(t: Throwable) {}
}// Still didn't work
So when I use more than four Futures then it keeps await forever. Is there some solution to fix it?
But it didn't work Could someone please suggest how to solve this issue?

Scheduled function not being called

Scheduling a function to be run every X seconds using Scala, this is what works for me :
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext
import ExecutionContext.Implicits.global
object Driver {
def main(args: Array[String]) {
val system = akka.actor.ActorSystem("system")
system.scheduler.schedule(0 seconds, 1 seconds)(println("beep"))
}
}
This implementation :
object Driver {
def main(args: Array[String]) {
val t = new java.util.Timer()
val task = new java.util.TimerTask {
def run() = println("Beep!")
}
t.schedule(task, 1000L, 1000L)
task.cancel()
}
}
And
import java.util.concurrent._
object Driver {
def main(args: Array[String]) {
val ex = new ScheduledThreadPoolExecutor(1)
val task = new Runnable {
def run() = println("Beep!")
}
val f = ex.scheduleAtFixedRate(task, 1, 1, TimeUnit.SECONDS)
f.cancel(false)
}
}
Do not run. They just hang and no output is displayed. What could be causing this ? If I debug the code then it appears to run sometimes, so this is environment related issue ?
I think that it will better not use interface Runnable and use only akka with scala for your job. You must use Cancellable for scheduling task an easy and correct way using actors is like this
From the akka documentation follow like this
import akka.actor.Actor
import akka.actor.Props
import akka.util.duration._
//Schedules to send the "foo"-message to the testActor after 50ms
system.scheduler.scheduleOnce(50 milliseconds, testActor, "foo")
//Schedules a function to be executed (send the current time) to the testActor after 50ms
system.scheduler.scheduleOnce(50 milliseconds) {
testActor ! System.currentTimeMillis
}
val Tick = "tick"
val tickActor = system.actorOf(Props(new Actor {
def receive = {
case Tick ⇒ //write here the function you want to execute
}
}))
//This will schedule to send the Tick-message
//to the tickActor after 0ms repeating every 50ms
val cancellable =
system.scheduler.schedule(0 milliseconds,
50 milliseconds,
tickActor,
Tick)
//This cancels further Ticks to be sent
cancellable.cancel()
this is a complete example that works:
using scala 2.11.6 and akka 2.3.8
package org.example
import akka.actor.{ ActorSystem, Props, Actor }
import scala.concurrent.duration._
import scala.language.postfixOps
/**
* Created by anquegi on 10/04/15.
*/
object ScheduledTaskScala extends App {
//Use the system's dispatcher as ExecutionContext
import system.dispatcher
val system = ActorSystem.create("sheduledtask");
val Tick = "tick"
val tickActor = system.actorOf(Props(new Actor {
def receive = {
case Tick ⇒ { Thread.sleep(1000); println("I'm executing a task"); }
}
}))
//This will schedule to send the Tick-message
//to the tickActor after 0ms repeating every 2 s
val cancellable =
system.scheduler.schedule(0 milliseconds,
2 seconds,
tickActor,
Tick)
Thread.sleep(10000)
cancellable.cancel()
}
The java.util.Timer's scheduler thread does not run as a daemon thread, so it may keep the application from terminating. So you should either
call t.cancel(), or
create your timer with isDaemon set true:
new java.util.Timer(true)
As for the second example, it's basically the same underlying problem, you should call ex.shutdown() to keep your application hanging.

Flaky onSuccess of Future.sequence

I wrote this method:
import scala.concurrent._
import ExecutionContext.Implicits.global
import scala.util.{ Success, Failure }
object FuturesSequence extends App {
val f1 = future {
1
}
val f2 = future {
2
}
val lf = List(f1, f2)
val seq = Future.sequence(lf)
seq.onSuccess {
case l => println(l)
}
}
I was expecting Future.sequence to gather a List[Future] into a Future[List] and then wait for every futures (f1 and f2 in my case) to complete before calling onSuccess on the Future[List] seq in my case.
But after many runs of this code, it prints "List(1, 2)" only once in a while and I can't figure out why it does not work as expected.
Try this for once,
import scala.concurrent._
import java.util.concurrent.Executors
import scala.util.{ Success, Failure }
object FuturesSequence extends App {
implicit val exec = ExecutionContext.fromExecutor(Executors.newCachedThreadPool)
val f1 = future {
1
}
val f2 = future {
2
}
val lf = List(f1, f2)
val seq = Future.sequence(lf)
seq.onSuccess {
case l => println(l)
}
}
This will always print List(1,2). The reason is simple, the exec above is an ExecutionContext of threads (not daemon threads) where as in your example the ExecutionContext was the default one implicitly taken from ExecutionContext.Implicits.global which contains daemon threads.
Hence being daemon, the process doesn't wait for seq future to be completed and terminates. if at all seq does get completed then it prints. But that doesn't happen always
The application is exiting before the future is completes.
You need to block until the future has completed. This can be achieved in a variety of ways, including changing the ExecutionContext, instantiating a new ThreadPool, Thread.sleep etc, or by using methods on scala.concurrent.Await
The simplest way for your code is by using Await.ready. This blocks on a future for a specified amount of time. In the modified code below, the application waits for 5 seconds before exiting.
Note also, the extra import scala.concurrent.duration so we can specify the time to wait.
import scala.concurrent._
import scala.concurrent.duration._
import java.util.concurrent.Executors
import scala.util.{ Success, Failure }
object FuturesSequence extends App {
val f1 = future {
1
}
val f2 = future {
2
}
val lf = List(f1, f2)
val seq = Future.sequence(lf)
seq.onSuccess {
case l => println(l)
}
Await.ready(seq, 5 seconds)
}
By using Await.result instead, you can skip the onSuccess method too, as it will return the resulting list to you.
Example:
val seq: List[Int] = Await.result(Future.sequence(lf), 5 seconds)
println(seq)

Why future example do not work?

I am reading akkaScala documentation, there is an example (p. 171 bottom)
// imports added for compilation
import scala.concurrent.{ExecutionContext, Future}
import ExecutionContext.Implicits.global
class Some {
}
object Some {
def main(args: Array[String]) {
// Create a sequence of Futures
val futures = for (i <- 1 to 1000) yield Future(i * 2)
val futureSum = Future.fold(futures)(0)(_ + _)
futureSum foreach println
}
}
I run it, but nothing happened. I mean that nothing was in console output. What is wrong?
You don't wait for the future to complete, so you create a race between the program exiting and the futures completing and the side-effect running. On your machine, the future seems to lose the race, on the commenters' who say "it works", the future is winning the race.
You can use Await to block on a future and wait for it to complete. This is something you should only be doing "at the ends of the world", you should very rarely actually be using Await...
// imports added for compilation
import scala.concurrent.{ExecutionContext, Future}
import ExecutionContext.Implicits.global
import scala.concurrent.duration._ // for the "1 second" syntax
import scala.concurrent.Await
class Some {
}
object Some {
def main(args: Array[String]) {
// Create a sequence of Futures
val futures = for (i <- 1 to 1000) yield Future(i * 2)
val futureSum = Future.fold(futures)(0)(_ + _)
// we map instead of foreach, to make sure that the side-effect is part of the future
// and we "await" for the future to complete (for 1 second)
Await.result(futureSum map println, 1 second)
}
}
As others have stated, the issue is the race condition where the futures are competing with the program terminating. The JVM has a concept of daemon threads. It waits for non-daemon threads to terminate but not daemon threads. So if you want to wait for threads to complete, use non-daemon threads.
The way threads are created for scala futures is using an implicit scala.concurrent.ExecutionContext. The one you use (import ExecutionContext.Implicits.global) starts daemon threads. However, it is possible to use non-daemon threads. So if you use an ExecutionContext with non-daemon threads, it will wait, which in your case is reasonable behaviour. Naively:
import scala.concurrent.Future
import scala.concurrent.ExecutionContextExecutor
import scala.concurrent.ExecutionContext
class MyExecutionContext extends ExecutionContext {
override def execute(runnable:Runnable) = {
val t = new Thread(runnable)
t.setDaemon(false)
t.start()
}
override def reportFailure(t:Throwable) = t.printStackTrace
}
object Some {
implicit lazy val context: ExecutionContext = new MyExecutionContext
def main(args: Array[String]) {
// Create a sequence of Futures
val futures = for (i <- 1 to 1000) yield Future(i * 2)
val futureSum = Future.fold(futures)(0)(_ + _)
futureSum foreach println
}
}
Careful with using the above ExecutionContext in production because it doesn't use a thread pool and can create unbounded threads, but the message is: you can control everything about the threads behind Futures through an ExecutionContext. Explore the various scala and akka contexts to find what you need, or if nothing suits, write your own.
Both of the following statement at the end of main function would help your need. As the above answers said, allow the future to complete. Main thread is different from the Future thread, as main completes, it terminates before Future thread.
Thread.sleep(500) //... Simple solution
Await.result(futureSum, Duration(500, MILLISECONDS)) //...have to import scala.concurrent.duration._ to use Duration object.