EECOLOR
EECOLOR

Reputation: 11244

How to run code in a separate thread?

I want to spawn a thread and run code in that thread. What are the options in Scala?

Example usage would be something like this:

Thread.currentThread setName "MyThread"

val myThreadExecutor = ???

val threadNamePromise = Promise[String]

future {
  myThreadExecutor run {
    val threadName = "MySpecialThread"
    Thread.currentThread setName threadName
    threadNamePromise success threadName
  }
}

Await.result(threadNamePromise.future, Duration.Inf)

future {
  myThreadExecutor run {
    println(Thread.currentThread.getName) // MySpecialThread
  }
}

future {
  myThreadExecutor run {
    println(Thread.currentThread.getName) // MySpecialThread
  }
}

println(Thread.currentThread.getName)   // MyThread

Is there anything in the built-in Scala library that I can use?

Edit

I updated the snippet to better reflect intent

Upvotes: 8

Views: 8691

Answers (5)

Eugene Lopatkin
Eugene Lopatkin

Reputation: 2737

ExecutionContext
  .fromExecutorService(Executors.newSingleThreadExecutor())
  .execute(() => {
    // your code here
  })

Upvotes: 0

EECOLOR
EECOLOR

Reputation: 11244

Using the answer of @alexwriteshere as a basis I created this implementation:

import java.util.concurrent.Executors
import scala.concurrent.future
import scala.concurrent.JavaConversions.asExecutionContext

class ApplicationThread {
  protected implicit val context = 
    asExecutionContext(Executors.newSingleThreadExecutor())

  def run(code: => Unit) = future(code)
}

Update

Thanks to @Dth for pointing out that this is the modern version:

import java.util.concurrent.Executors
import scala.concurrent.{ExecutionContext, Future}

class ApplicationThread {
  protected implicit val context = 
    ExecutionContext.fromExecutorService(Executors.newSingleThreadExecutor())

  def run(code: => Unit) = Future(code)
}

Upvotes: 3

Marius Danila
Marius Danila

Reputation: 10411

Yes, there is. You can use the scala.concurrent from the standard library. More specifically, you can use futures - highly composable asynchronous computations.

import java.util.concurrent.Executors
import concurrent.{ExecutionContext, Await, Future}
import concurrent.duration._

object Main extends App {

  // single threaded execution context
  implicit val context = ExecutionContext.fromExecutor(Executors.newSingleThreadExecutor())

  val f = Future {
    println("Running asynchronously on another thread")
  }

  f.onComplete { _ =>
    println("Running when the future completes")
  }

  Await.ready(f, 5.seconds) // block synchronously for this future to complete

}

Futures run in an execution context, which is an abstraction for thread pools. This context can be passed implicitly. In the above example, we used a global one, defined by the Scala library - but you can control this aspect of your program by allocating many execution contexts.

The snippet only does what you asked - running code concurrently. However, futures are much more than that - they allow you to compute values asynchronously, compose multiple futures to obtain results with dependencies amongst them, or in parallel.

Here's an intro: http://docs.scala-lang.org/overviews/core/futures.html

Upvotes: 8

lostsoul29
lostsoul29

Reputation: 756

Based on @EECOLOR'S answer, here's a generic, reusable method that executes arbitrary code on a separate thread:

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

def executeParallelTask[T](code: => T): Future[T] = Future(code)

Upvotes: 1

Alex Yarmula
Alex Yarmula

Reputation: 10667

Besides the standard concurrency library, there's a few more. For example, there's com.twitter / util-core library that lets you do:

val pool = FuturePool.unboundedPool
pool {
   <code>
}

Your example would look like:

Thread.currentThread setName "MyThread"

// because you have to be using a single-threaded one to get the same name
val pool = FuturePool(Executors.newSingleThreadExecutor())

pool {
  Thread.currentThread setName "MySpecialThread"
}

pool {
  println(Thread.currentThread.getName) // MySpecialThread
}

println(Thread.currentThread.getName)

Upvotes: 2

Related Questions