This page is no longer maintained — Please continue to the home page at www.scala-lang.org

actor() as new Thread()

7 replies
Fedor Bobin
Joined: 2010-04-19,
User offline. Last seen 42 years 45 weeks ago.

Hello.

Why this code prints only 1,2,3,4 (but not other numbers)

{
import scala.actors.Actor._
for (i <- 1 to 10000) {
actor {
val num = i
//logger.debug(num)
println(num)
try {
Thread.sleep(Integer.MAX_VALUE)
} catch {
case e: Throwable => println("error", e)
}
println("exited " + num)
}
}
Thread.sleep(1000)
}

Fedor Bobin.
bobin@reksoft.ru

Kevin Wright 2
Joined: 2010-05-30,
User offline. Last seen 26 weeks 4 days ago.
Re: actor() as new Thread()
My guess...
Because you've started 4 actors on a size 4 thread pool, then blocked them all for Integer.MAX_VALUE milliseconds
In the meantime, your main program only waits for 1000 milliseconds, then exits.
Was it really your intent to have 10,000 actors, all sleeping in parallel?


On 8 June 2010 06:57, Fedor Bobin <bobin@reksoft.ru> wrote:


Hello.

Why this code prints only 1,2,3,4 (but not other numbers)

 {
   import scala.actors.Actor._
   for (i <- 1 to 10000) {
     actor {
       val num = i
       //logger.debug(num)
       println(num)
       try {
         Thread.sleep(Integer.MAX_VALUE)
       } catch {
         case e: Throwable => println("error", e)
       }
       println("exited " + num)
     }
   }
   Thread.sleep(1000)
 }


Fedor Bobin.
bobin@reksoft.ru




--
Kevin Wright

mail/google talk: kev.lee.wright@gmail.com
wave: kev.lee.wright@googlewave.com
skype: kev.lee.wright
twitter: @thecoda

Fedor Bobin
Joined: 2010-04-19,
User offline. Last seen 42 years 45 weeks ago.
Re: actor() as new Thread()

From the scala actors tutorial (http://www.scala-lang.org/node/242)

>>Actors are executed on a thread pool. Initially, there are 4 worker
threads. The thread pool grows if all worker threads are blocked but there
are still remaining tasks to be processed.

It seems that thread pool does not grow. Why?

bobin@reksoft.ru

-----Kevin Wright wrote: -----

To: Fedor Bobin
From: Kevin Wright
Date: 06/08/2010 10:12AM
Cc: scala-user@listes.epfl.ch
Subject: Re: [scala-user] actor() as new Thread()

My guess...

Because you've started 4 actors on a size 4 thread pool, then blocked them
all for Integer.MAX_VALUE milliseconds
In the meantime, your main program only waits for 1000 milliseconds, then
exits.

Was it really your intent to have 10,000 actors, all sleeping in parallel?

On 8 June 2010 06:57, Fedor Bobin < bobin@reksoft.ru > wrote:

Hello.

Why this code prints only 1,2,3,4 (but not other numbers)

{
import scala.actors.Actor._
for (i <- 1 to 10000) {
actor {
val num = i
//logger.debug(num)
println(num)
try {
Thread.sleep(Integer.MAX_VALUE)
} catch {
case e: Throwable => println("error", e)
}
println("exited " + num)
}
}
Thread.sleep(1000)
}

Fedor Bobin.
bobin@reksoft.ru

--
Kevin Wright

mail/google talk: kev.lee.wright@gmail.com
wave: kev.lee.wright@googlewave.com
skype: kev.lee.wright
twitter: @thecoda

Kevin Wright 2
Joined: 2010-05-30,
User offline. Last seen 26 weeks 4 days ago.
Re: actor() as new Thread()
And in the subsequent paragraph:
    "... thread-blocking operations, such as receive (or even wait), ..."

blocking is when a thread is explicitly waits for some external action before it can continue, sleep doesn't fall into this category.Sleep is just a bit of internal thumb-twiddling


On 8 June 2010 07:25, Fedor Bobin <bobin@reksoft.ru> wrote:
From the scala actors tutorial (http://www.scala-lang.org/node/242)

>>Actors are executed on a thread pool. Initially, there are 4 worker
threads. The thread pool grows if all worker threads are blocked but there
are still remaining tasks to be processed.

It seems that thread pool does not grow. Why?

bobin@reksoft.ru

-----Kevin Wright <kev.lee.wright@gmail.com> wrote: -----

To: Fedor Bobin <bobin@reksoft.ru>
From: Kevin Wright <kev.lee.wright@gmail.com>
Date: 06/08/2010 10:12AM
Cc: scala-user@listes.epfl.ch
Subject: Re: [scala-user] actor() as new Thread()

My guess...

Because you've started 4 actors on a size 4 thread pool, then blocked them
all for  Integer.MAX_VALUE milliseconds
In the meantime, your main program only waits for 1000 milliseconds, then
exits.

Was it really your intent to have 10,000 actors, all sleeping in parallel?



On 8 June 2010 06:57, Fedor Bobin < bobin@reksoft.ru > wrote:


Hello.

Why this code prints only 1,2,3,4 (but not other numbers)

 {
  import scala.actors.Actor._
  for (i <- 1 to 10000) {
    actor {
      val num = i
      //logger.debug(num)
      println(num)
      try {
        Thread.sleep(Integer.MAX_VALUE)
      } catch {
        case e: Throwable => println("error", e)
      }
      println("exited " + num)
    }
  }
  Thread.sleep(1000)
 }


Fedor Bobin.
bobin@reksoft.ru




--
Kevin Wright

mail/google talk: kev.lee.wright@gmail.com
wave: kev.lee.wright@googlewave.com
skype: kev.lee.wright
twitter: @thecoda





--
Kevin Wright

mail/google talk: kev.lee.wright@gmail.com
wave: kev.lee.wright@googlewave.com
skype: kev.lee.wright
twitter: @thecoda

Philipp Haller
Joined: 2009-01-13,
User offline. Last seen 42 years 45 weeks ago.
Re: actor() as new Thread()

Fedor Bobin wrote:
> From the scala actors tutorial (http://www.scala-lang.org/node/242)
>
>>> Actors are executed on a thread pool. Initially, there are 4 worker
> threads. The thread pool grows if all worker threads are blocked but there
> are still remaining tasks to be processed.
>
> It seems that thread pool does not grow. Why?

In Scala 2.8.0 the default thread pool only grows when actors are
blocked in a `receive`, `receiveWithin`, or some other thread-blocking
operation implemented by the actors library (such as a synchronous
send). In these cases, the thread pool can be resized efficiently.

However, it is also possible to use
`scala.actors.scheduler.ResizableThreadPoolScheduler` (*), which resizes
the pool heuristically also for other operations that occupy a thread
for a possibly indefinite time.

Using the default scheduler your code works as expected if you replace
`Thread.sleep(time)` with `receiveWithin(time) { case TIMEOUT => }`.

Cheers,
Philipp

(*) To use a custom scheduler you have to start a new instance, and
override `def scheduler` in trait `Reactor`/`Actor` to return that instance.

> To: Fedor Bobin
> From: Kevin Wright
> Date: 06/08/2010 10:12AM
> Cc: scala-user@listes.epfl.ch
> Subject: Re: [scala-user] actor() as new Thread()
>
> My guess...
>
> Because you've started 4 actors on a size 4 thread pool, then blocked them
> all for Integer.MAX_VALUE milliseconds
> In the meantime, your main program only waits for 1000 milliseconds, then
> exits.
>
> Was it really your intent to have 10,000 actors, all sleeping in parallel?
>
>
>
> On 8 June 2010 06:57, Fedor Bobin < bobin@reksoft.ru > wrote:
>
>
> Hello.
>
> Why this code prints only 1,2,3,4 (but not other numbers)
>
> {
> import scala.actors.Actor._
> for (i <- 1 to 10000) {
> actor {
> val num = i
> //logger.debug(num)
> println(num)
> try {
> Thread.sleep(Integer.MAX_VALUE)
> } catch {
> case e: Throwable => println("error", e)
> }
> println("exited " + num)
> }
> }
> Thread.sleep(1000)
> }
>
>
> Fedor Bobin.
> bobin@reksoft.ru
>
>
>
>
> --
> Kevin Wright
>
> mail/google talk: kev.lee.wright@gmail.com
> wave: kev.lee.wright@googlewave.com
> skype: kev.lee.wright
> twitter: @thecoda
>
>

Erik Engbrecht
Joined: 2008-12-19,
User offline. Last seen 3 years 18 weeks ago.
Re: actor() as new Thread()
Philipp, Does that mean that if actors are using the default scheduler, and a sufficient number block on IO operations, the thread pool will not grow?   What about if a sufficient number of actors are engaged in long-running computations (meaning they don't block but they do hog the thread)?   If either of these cases are true, I would suggest adding something in the API docs (maybe it's already there, sorry, didn't check) telling users that if they are doing IO or long running computations then they should either use a different scheduler or manually configure the thread pool to be large enough to prevent starvation.  A lot of people do IO from actors.   -Erik

On Mon, Jun 28, 2010 at 10:59 AM, Philipp Haller <philipp.haller@epfl.ch> wrote:
Fedor Bobin wrote:
> From the scala actors tutorial (http://www.scala-lang.org/node/242)
>
>>> Actors are executed on a thread pool. Initially, there are 4 worker
> threads. The thread pool grows if all worker threads are blocked but there
> are still remaining tasks to be processed.
>
> It seems that thread pool does not grow. Why?

In Scala 2.8.0 the default thread pool only grows when actors are
blocked in a `receive`, `receiveWithin`, or some other thread-blocking
operation implemented by the actors library (such as a synchronous
send). In these cases, the thread pool can be resized efficiently.

However, it is also possible to use
`scala.actors.scheduler.ResizableThreadPoolScheduler` (*), which resizes
the pool heuristically also for other operations that occupy a thread
for a possibly indefinite time.

Using the default scheduler your code works as expected if you replace
`Thread.sleep(time)` with `receiveWithin(time) { case TIMEOUT => }`.

Cheers,
Philipp

(*) To use a custom scheduler you have to start a new instance, and
override `def scheduler` in trait `Reactor`/`Actor` to return that instance.



> To: Fedor Bobin <bobin@reksoft.ru>
> From: Kevin Wright <kev.lee.wright@gmail.com>
> Date: 06/08/2010 10:12AM
> Cc: scala-user@listes.epfl.ch
> Subject: Re: [scala-user] actor() as new Thread()
>
> My guess...
>
> Because you've started 4 actors on a size 4 thread pool, then blocked them
> all for  Integer.MAX_VALUE milliseconds
> In the meantime, your main program only waits for 1000 milliseconds, then
> exits.
>
> Was it really your intent to have 10,000 actors, all sleeping in parallel?
>
>
>
> On 8 June 2010 06:57, Fedor Bobin < bobin@reksoft.ru > wrote:
>
>
> Hello.
>
> Why this code prints only 1,2,3,4 (but not other numbers)
>
>  {
>    import scala.actors.Actor._
>    for (i <- 1 to 10000) {
>      actor {
>        val num = i
>        //logger.debug(num)
>        println(num)
>        try {
>          Thread.sleep(Integer.MAX_VALUE)
>        } catch {
>          case e: Throwable => println("error", e)
>        }
>        println("exited " + num)
>      }
>    }
>    Thread.sleep(1000)
>  }
>
>
> Fedor Bobin.
> bobin@reksoft.ru
>
>
>
>
> --
> Kevin Wright
>
> mail/google talk: kev.lee.wright@gmail.com
> wave: kev.lee.wright@googlewave.com
> skype: kev.lee.wright
> twitter: @thecoda
>
>




--
http://erikengbrecht.blogspot.com/
Erik Engbrecht
Joined: 2008-12-19,
User offline. Last seen 3 years 18 weeks ago.
Re: actor() as new Thread()
Thanks Philipp!
For those not following the commit log:https://lampsvn.epfl.ch/trac/scala/changeset/22414/scala/trunk/src/actors

On Mon, Jun 28, 2010 at 11:09 AM, Erik Engbrecht <erik.engbrecht@gmail.com> wrote:
Philipp, Does that mean that if actors are using the default scheduler, and a sufficient number block on IO operations, the thread pool will not grow?   What about if a sufficient number of actors are engaged in long-running computations (meaning they don't block but they do hog the thread)?   If either of these cases are true, I would suggest adding something in the API docs (maybe it's already there, sorry, didn't check) telling users that if they are doing IO or long running computations then they should either use a different scheduler or manually configure the thread pool to be large enough to prevent starvation.  A lot of people do IO from actors.   -Erik

On Mon, Jun 28, 2010 at 10:59 AM, Philipp Haller <philipp.haller@epfl.ch> wrote:
Fedor Bobin wrote:
> From the scala actors tutorial (http://www.scala-lang.org/node/242)
>
>>> Actors are executed on a thread pool. Initially, there are 4 worker
> threads. The thread pool grows if all worker threads are blocked but there
> are still remaining tasks to be processed.
>
> It seems that thread pool does not grow. Why?

In Scala 2.8.0 the default thread pool only grows when actors are
blocked in a `receive`, `receiveWithin`, or some other thread-blocking
operation implemented by the actors library (such as a synchronous
send). In these cases, the thread pool can be resized efficiently.

However, it is also possible to use
`scala.actors.scheduler.ResizableThreadPoolScheduler` (*), which resizes
the pool heuristically also for other operations that occupy a thread
for a possibly indefinite time.

Using the default scheduler your code works as expected if you replace
`Thread.sleep(time)` with `receiveWithin(time) { case TIMEOUT => }`.

Cheers,
Philipp

(*) To use a custom scheduler you have to start a new instance, and
override `def scheduler` in trait `Reactor`/`Actor` to return that instance.



> To: Fedor Bobin <bobin@reksoft.ru>
> From: Kevin Wright <kev.lee.wright@gmail.com>
> Date: 06/08/2010 10:12AM
> Cc: scala-user@listes.epfl.ch
> Subject: Re: [scala-user] actor() as new Thread()
>
> My guess...
>
> Because you've started 4 actors on a size 4 thread pool, then blocked them
> all for  Integer.MAX_VALUE milliseconds
> In the meantime, your main program only waits for 1000 milliseconds, then
> exits.
>
> Was it really your intent to have 10,000 actors, all sleeping in parallel?
>
>
>
> On 8 June 2010 06:57, Fedor Bobin < bobin@reksoft.ru > wrote:
>
>
> Hello.
>
> Why this code prints only 1,2,3,4 (but not other numbers)
>
>  {
>    import scala.actors.Actor._
>    for (i <- 1 to 10000) {
>      actor {
>        val num = i
>        //logger.debug(num)
>        println(num)
>        try {
>          Thread.sleep(Integer.MAX_VALUE)
>        } catch {
>          case e: Throwable => println("error", e)
>        }
>        println("exited " + num)
>      }
>    }
>    Thread.sleep(1000)
>  }
>
>
> Fedor Bobin.
> bobin@reksoft.ru
>
>
>
>
> --
> Kevin Wright
>
> mail/google talk: kev.lee.wright@gmail.com
> wave: kev.lee.wright@googlewave.com
> skype: kev.lee.wright
> twitter: @thecoda
>
>




--
http://erikengbrecht.blogspot.com/



--
http://erikengbrecht.blogspot.com/
Philipp Haller
Joined: 2009-01-13,
User offline. Last seen 42 years 45 weeks ago.
Re: actor() as new Thread()

Following up on this, a robust way to do blocking is using the
`ManagedBlocker` interface, which is new in Scala 2.8. Using this
interface the thread pool temporarily grows if necessary to avoid
starvation when invoking custom blocking methods, such as for blocking
I/O. In particular, this is fully supported by the default thread pool.

Here is the original example modified to use `ManagedBlocker`. The
helper method `mayWait` takes a block, which may contain invocations of
(arbitrary) blocking methods. If you run the example, you'll see that
the pool will grow up to its maximum size (256 threads by default).

import scala.concurrent.ManagedBlocker
for (i <- 1 to 10000) {
(new Actor {

def mayWait(fun: => Unit) {
scheduler.managedBlock(new ManagedBlocker {
@volatile var done = false
def block() = { fun; done = true; done }
def isReleasable = { done == true }
})
}

def act() {
val num = i
println(num)
try {
mayWait {
Thread.sleep(Integer.MAX_VALUE)
}
} catch {
case e: Throwable => println("error", e)
}
println("exited " + num)
}

}).start()
}

Of course, there is room for documenting this more extensively. In fact,
I've been working on this. Hopefully it's going to be released soon.

Cheers,
Philipp

Philipp Haller wrote:
> Fedor Bobin wrote:
>> From the scala actors tutorial (http://www.scala-lang.org/node/242)
>>
>>>> Actors are executed on a thread pool. Initially, there are 4 worker
>> threads. The thread pool grows if all worker threads are blocked but there
>> are still remaining tasks to be processed.
>>
>> It seems that thread pool does not grow. Why?
>
> In Scala 2.8.0 the default thread pool only grows when actors are
> blocked in a `receive`, `receiveWithin`, or some other thread-blocking
> operation implemented by the actors library (such as a synchronous
> send). In these cases, the thread pool can be resized efficiently.
>
> However, it is also possible to use
> `scala.actors.scheduler.ResizableThreadPoolScheduler` (*), which resizes
> the pool heuristically also for other operations that occupy a thread
> for a possibly indefinite time.
>
> Using the default scheduler your code works as expected if you replace
> `Thread.sleep(time)` with `receiveWithin(time) { case TIMEOUT => }`.
>
> Cheers,
> Philipp
>
> (*) To use a custom scheduler you have to start a new instance, and
> override `def scheduler` in trait `Reactor`/`Actor` to return that instance.
>
>
>
>> To: Fedor Bobin
>> From: Kevin Wright
>> Date: 06/08/2010 10:12AM
>> Cc: scala-user@listes.epfl.ch
>> Subject: Re: [scala-user] actor() as new Thread()
>>
>> My guess...
>>
>> Because you've started 4 actors on a size 4 thread pool, then blocked them
>> all for Integer.MAX_VALUE milliseconds
>> In the meantime, your main program only waits for 1000 milliseconds, then
>> exits.
>>
>> Was it really your intent to have 10,000 actors, all sleeping in parallel?
>>
>>
>>
>> On 8 June 2010 06:57, Fedor Bobin < bobin@reksoft.ru > wrote:
>>
>>
>> Hello.
>>
>> Why this code prints only 1,2,3,4 (but not other numbers)
>>
>> {
>> import scala.actors.Actor._
>> for (i <- 1 to 10000) {
>> actor {
>> val num = i
>> //logger.debug(num)
>> println(num)
>> try {
>> Thread.sleep(Integer.MAX_VALUE)
>> } catch {
>> case e: Throwable => println("error", e)
>> }
>> println("exited " + num)
>> }
>> }
>> Thread.sleep(1000)
>> }
>>
>>
>> Fedor Bobin.
>> bobin@reksoft.ru
>>
>>
>>
>>
>> --
>> Kevin Wright
>>
>> mail/google talk: kev.lee.wright@gmail.com
>> wave: kev.lee.wright@googlewave.com
>> skype: kev.lee.wright
>> twitter: @thecoda
>>
>>
>

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland