- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
actor() as new Thread()
Tue, 2010-06-08, 06:58
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
Tue, 2010-06-08, 07:37
#2
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?
-----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
Tue, 2010-06-08, 07:57
#3
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:
--
Kevin Wright
mail/google talk: kev.lee.wright@gmail.com
wave: kev.lee.wright@googlewave.com
skype: kev.lee.wright
twitter: @thecoda
"... 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
Mon, 2010-06-28, 16:07
#4
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
>
>
Mon, 2010-06-28, 16:17
#5
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:
--
http://erikengbrecht.blogspot.com/
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/
Tue, 2010-06-29, 03:17
#6
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:
--
http://erikengbrecht.blogspot.com/
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/
Tue, 2010-06-29, 13:47
#7
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
>>
>>
>
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:
--
Kevin Wright
mail/google talk: kev.lee.wright@gmail.com
wave: kev.lee.wright@googlewave.com
skype: kev.lee.wright
twitter: @thecoda