Re: multithreaded tasks

103 views
Skip to first unread message

jason...@gmail.com

unread,
Oct 17, 2012, 12:05:22 AM10/17/12
to kilimt...@googlegroups.com
Hi,

My sample project illustrates a fundamental misunderstanding that I
have had in regard to how actors and multi-threading works. I was
hoping that my KilimWaiter would not be blocked by "Task2" taking
forever.

What would be the recommended way of allowing "Task2" to take its own
sweet time but allow all the other tasks to complete in the meantime.
At the moment obviously "Task2" blocks all other tasks from executing.

Can I somehow have multiple instances of KilimWaiter all consuming the
same mailbox?

I hope someone can provide some guidance. In the meantime I am going
to continue playing around and try to come up with something myself.

Kind regards
Jason
kilim-get-test.tar.gz

Sriram Srinivasan

unread,
Oct 17, 2012, 1:28:08 AM10/17/12
to kilimt...@googlegroups.com
> Can I somehow have multiple instances of KilimWaiter all consuming the
> same mailbox?

Mailboxes are single consumer (single getter), multiple producer entities. If two actors wait on the same mailbox, the mailbox will raise a runtime exception.

There are two options. One is to create your own style of mailbox that allows multiple producers as well. Use Mailbox and Cell as your starting point. I would not recommend this.

The other option is to use mailbox.select, which allows one to wait on n mailboxes. The select unblocks when one or more of the mailboxes have a message.

--sriram.

jason...@gmail.com

unread,
Oct 17, 2012, 2:28:11 AM10/17/12
to kilimt...@googlegroups.com
Hi,

Thanks for that, and I realised after I sent the message that multiple
Tasks cannot listen on a single mailbox. So does anyone have any
suggestions as to how I would make my Task multithreaded, so that I
can process multiple messages off the Mailbox in parallel, rather than
serial?

The solution to have a single Task waiting on multiple mailboxes will
actually make my problem worse, as I will have a single Task as a
bottle neck for multiple producers.

Basically my scenario is this:

I have a producer who produces multiple 'request' messages and posts
them onto a processor mailbox (in my example this is the KilimWaiter
actor), I want the KilimWaiter to be able
to process request messages in parallel.

Currently what happens is the kilimwaiter (processor actor) processes
the messages serially which is not what I was expecting.

I am hoping there is an obvious pattern i am missing? I don't want to
have to try and round robbin to multiple processor actors so that I
can artificially implement parallism for this task.

Would appreciate any assistance given

Tony Arcieri

unread,
Oct 17, 2012, 3:20:20 AM10/17/12
to kilimt...@googlegroups.com
On Tue, Oct 16, 2012 at 11:28 PM, <jason...@gmail.com> wrote:
Thanks for that, and I realised after I sent the message that multiple
Tasks cannot listen on a single mailbox.  So does anyone have any
suggestions as to how I would make my Task multithreaded, so that I
can process multiple messages off the Mailbox in parallel, rather than
serial?

You're running into the fundamental disconnect between actors and CSP: actors are many-to-one, and CSP is many-to-many.

You want a channel that multiple consumers can consume from.

The actor-based solution is to make the channel and actor and have it dispatch events to many consumers. 

--
Tony Arcieri

Jason Pell

unread,
Oct 17, 2012, 3:43:23 AM10/17/12
to kilimt...@googlegroups.com
I kind of figured that might be the problem, that I was expecting more
from actor model such as Kilim than they can deliver.

Was your last sentence a proposed direction. I am trying to imagine how I might
do that with Kilim? There is no concept of a channel in kilim other
than Mailbox, and mailboxes are single consumer only.

I still feel like there is a solution to this sitting just outside my
peripheral vision.

The actor model of mailboxes and decoupled actors is very attractive
for my application which is a workflow execution solution. Each node
on the workflow as a kilim actor is working very well, its just this
multi-threaded thing when I want to be able to execute parallel
workflows through the same set of nodes, that is the problem.

Tony Arcieri

unread,
Oct 17, 2012, 3:51:59 AM10/17/12
to kilimt...@googlegroups.com
On Wed, Oct 17, 2012 at 12:43 AM, Jason Pell <ja...@pellcorp.com> wrote:
Was your last sentence a proposed direction.

Yes, CSP and the actor model are two sides of the same coin... two fundamentally related ideas that solve the same problem in different ways. Either can be implemented with the other.

If you want multiple actors to consume the same "mailbox", you can have a single actor that buffers messages (ala a CSP channel) and several other actors requesting to consume from it. The basic idea is you implement a CSP channel as an actor.

--
Tony Arcieri

jason...@gmail.com

unread,
Oct 17, 2012, 4:49:05 AM10/17/12
to kilimt...@googlegroups.com

I think I managed to get further. Not sure if it was what you were talking about. What I did is I moved the logic out of KilimWaiter into a single use actor. I create this actor and start it and stick the message in the inbox. So now the "Task2" can take as long as it wants.

I just need to solve this same problem for fork join pattern probably the same way.

Sent from my Galaxy S2

jason...@gmail.com

unread,
Oct 17, 2012, 6:36:22 AM10/17/12
to kilimt...@googlegroups.com

Not sure my description was very clear.

Basically KilimWaiter looks like this now:

while(true) {
  Message msg = inbox.get();
KilimWorkerTask task = new KilimWorkerTask();
task.start();
task.getInbox().put(msg);
}

The worker task is single use, so no while loop.

Any issues other than lots of one use objects?

gzso...@gmail.com

unread,
Oct 17, 2012, 6:42:40 AM10/17/12
to jason...@gmail.com, kilimt...@googlegroups.com, kilimt...@googlegroups.com
Why can't you create and use a java.util.concurrent.ExecutorService to process concurrent tasks ? This is what it's designed for.  

BR,
 Zsombor

jason...@gmail.com

unread,
Oct 17, 2012, 6:59:23 AM10/17/12
to gzso...@gmail.com, kilimt...@googlegroups.com

Already using kilim heavily do not want to change it out if I can help it. Besides I love how well actors and mailboxes map to my domain I just have a couple of long running tasks that I cannot split into smaller pieces do need to parallel them.

Sent from my Galaxy S2

gzso...@gmail.com

unread,
Oct 17, 2012, 7:11:32 AM10/17/12
to jason...@gmail.com, kilimt...@googlegroups.com
I didn't suggest you to remove kilim from your app, I only said, that it would be much simpler to use solution which is engineered for this problem to solve (concurrent long running tasks), and not to force this model into kilim. Your solution - if I understand correctly - is equivalent with spawning separate threads for every tasks, in a complicated way, without limits.

jason...@gmail.com

unread,
Oct 17, 2012, 7:14:05 AM10/17/12
to kilimt...@googlegroups.com

Actually no since kilim is scheduler is limited to a certain number of threads. All i am doing is adding some additional tasks to be executed, but still on the same number of threads.

My solution is certainly not as drastic or bad as you indicate. I actually suspect its reasonable, looking for a kilim user to comment.

jason...@gmail.com

unread,
Oct 17, 2012, 7:25:42 AM10/17/12
to kilimt...@googlegroups.com

Also these longer running process are sometimes 10s of seconds but often sub second. And they need to be executed within a chain of actors as i am implementing a workflow solution and some actors can take longer so really looking to get them working with kilim.

I realise i may be stretching the usecase but kilim is a great fit otherwise.

Sriram Srinivasan

unread,
Oct 17, 2012, 8:13:10 AM10/17/12
to kilimt...@googlegroups.com

On Oct 17, 2012, at 11:58 AM, jason...@gmail.com wrote:


I have a producer who produces multiple 'request' messages and posts
them onto a processor mailbox (in my example this is the KilimWaiter
actor), I want the KilimWaiter to be able
to process request messages in parallel.


Currently what happens is the kilimwaiter (processor actor) processes
the messages serially which is not what I was expecting.

I am hoping there is an obvious pattern i am missing?  I don't want to
have to try and round robbin to multiple processor actors so that I
can artificially implement parallism for this task.


Do you have a good reason to use many-many lightweight tasks in this program (not just in the producer-consumer part)? If not, and if it is a standard producer-consumer model with relatively few producers and consumers,  I would just use regular Java threads and one of the many sound inter-thread messaging patterns (ArrayBlockingQueue or  the LMAX disrupter), or if the processing is short-lived, the Java executor service. 

If the processing tasks are longer lived (possibly waiting on I/O or doing other coordination in addition to doing the processing), and if your design creates thousands of such long-lived tasks, then using Kilim tasks for the processing is a good choice. I suspect that this isn't so in your case, because you don't care which task picks up the message. Merely using tasks as a proxy for threads is not a good idea. 

In any case, to answer the question of how to efficiently have a producer spray messages to one of n waiting tasks, I'd write the dual of Mailbox.select.  select waits for one of n mailboxes to have a message, and returns "i" if the i'th mailbox (in its param list) has a message. If none of them, have a message, it registers itself as a listener with all n mailboxes, and pauses the receiving task.   The best way to solve this is to do "select" for "put" instead of get. It should be almost a direct translation of Mailbox.select. 

--sriram. 

Sriram Srinivasan

unread,
Oct 17, 2012, 8:19:16 AM10/17/12
to kilimt...@googlegroups.com
Actually, a simpler option occurred to me. If the consumer tasks don't have much of a setup, the producer can create a consumer task on the fly, with the message to be processed. No need for mailboxes even. You can rate-limit the number of consumer tasks by having the producer track the finish of consumer tasks.

But as I said before, it is worth it to use Kilim only if the tasks have other coordination or waiting to do. Otherwise, just use the executor service.




Sriram Srinivasan

unread,
Oct 17, 2012, 8:20:14 AM10/17/12
to kilimt...@googlegroups.com
Oops. Sorry. I didn't realize there were so many messages on this thread before I began responding …

--sriram.



jason...@gmail.com

unread,
Oct 17, 2012, 9:18:41 AM10/17/12
to kilimt...@googlegroups.com

Its potentially a very large graph of actors to implement a workflow.  Each actor represents a node each outgoing mail box represents a edge to another node.  Most nodes will have at least 2 or more out going edges.

I will certainly look at your suggestions.

I already was exploring the temporary consumer idea.

I think it would already be throttled by the number of kilim threads available would it not?

also I do care what task picks up the message. I actually wanted to be able to have a task be able to be processing multiple messages at once.

Anyway your last suggestion is close to what I was thinking and I will also evaluate an alternative inter thread messaging pattern as well.

Appreciate everyone's responses so far. Very helpful

Sent from my Galaxy S2

jason...@gmail.com

unread,
Oct 17, 2012, 9:25:30 AM10/17/12
to kilimt...@googlegroups.com

Probably not 1000s though maybe 100 or so on average

Sriram Srinivasan

unread,
Oct 17, 2012, 9:29:17 AM10/17/12
to kilimt...@googlegroups.com

On Oct 17, 2012, at 6:48 PM, jason...@gmail.com wrote:

> Its potentially a very large graph of actors to implement a workflow. Each actor represents a node each outgoing mail box represents a edge to another node. Most nodes will have at least 2 or more out going edges.
>
> I will certainly look at your suggestions.
>
> I already was exploring the temporary consumer idea.
>
> I think it would already be throttled by the number of kilim threads available would it not?

The number of running tasks is limited by the thread pool, but not the number of _runnable_ tasks.

>
> also I do care what task picks up the message. I actually wanted to be able to have a task be able to be processing multiple messages at once.

I see. You have two types of nodes then; for each workflow node, you have slave processing nodes. I see no reason why you can't spawn a task per slave processing node as the need arises, and let that task run to completion. It is no different from an ExecutorService task.

--sriram.

Jason Pell

unread,
Oct 18, 2012, 1:15:01 AM10/18/12
to kilimt...@googlegroups.com
What I ended up doing initially is moving the logic to a hidden method called:

public void act(Message s) throws Pausable {
...
}

And the execute method:

public void execute() throws Pausable {
while (true) {
final Message s = mb.get();
Task worker = new Task() {
public void execute() throws Pausable {
act(s);
}
};
worker.start();
}
}

I will look at how I throttle this down to a limited number of newly
spawned tasks later, but it does the job, and in our existing code I
could slip this change into our kilim Actor base classes that extend
Task very simply.
Reply all
Reply to author
Forward
0 new messages