Can a Runnable add a new thread to a ExecutorService?

Hello,

I have a question about the ExecutorService. Lets says I have the following scenarion:

import java.util.concurrent.*;

import java.util.Random;

publicclass UsePool{

publicstaticvoid main(String args[]){

Random random =new Random();

ExecutorService executor =

Executors.newFixedThreadPool(3);

// Sum up wait times to know when to shutdown

int waitTime = 500;

for (int i=0; i<10; i++){

String name ="NamePrinter " + i;

int time = random.nextInt(1000);

waitTime += time;

Runnable runner =new NamePrinter(name, time);

System.out.println("Adding: " + name +" / " + time);

executor.execute(runner);

}

try{

Thread.sleep(waitTime);

executor.shutdown();

executor.awaitTermination

(waitTime, TimeUnit.MILLISECONDS);

}catch (InterruptedException ignored){

}

System.exit(0);

}

}

publicclass NamePrinterimplements Runnable{

privatefinal String name;

privatefinalint delay;

public NamePrinter(String name,int delay){

this.name = name;

this.delay = delay;

}

publicvoid run(){

System.out.println("Starting: " + name);

try{

Thread.sleep(delay);

}catch (InterruptedException ignored){

}

System.out.println("Done with: " + name);

}

}

What I'd like to do, is modify this scenario so that the NamePrinter class can add other NamePrinter threads to the ExecutorService in UsePool - is it possible to do that? Any ideas how?

[3267 byte] By [BigBadBurrowa] at [2007-11-26 18:37:55]
# 1
> how?Why?It seems what you really want is java.util.Timer, but I'm just guessing.
ejpa at 2007-7-9 6:11:59 > top of Java-index,Java Essentials,Java Programming...
# 2

Why? Because in my situation a thread needs to start other threads to add to the ExecutorService.

For example, let's say I'm recursing a tree; I start with a single thread for the root node, then discover there are three children, I want to add three new threads for these child nodes. These child nodes may then also have child nodes and I'll need to add more threads for those etc etc.

So in my case I don't know at the start how big the tree is. I would have thought this was a regular kind of problem that would need solving as quite a lot of time programmers won't know at the start how big a process is at the start.

Clearer?

BigBadBurrowa at 2007-7-9 6:11:59 > top of Java-index,Java Essentials,Java Programming...
# 3

> What I'd like to do, is modify this scenario so that

> the NamePrinter class can add other NamePrinter

> threads to the ExecutorService in UsePool - is it

> possible to do that? Any ideas how?

Well, yeah. Anything that has a reference to an object can call one of that object's public methods. So pass a reference to the ExecutorService object to the NamePrinter object and go to it.

DrClapa at 2007-7-9 6:11:59 > top of Java-index,Java Essentials,Java Programming...
# 4

mmmm.... not sure about that, maybe I misunderstood your suggestion, but this is what I tried:

import java.util.concurrent.Executors;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.TimeUnit;

import java.util.Random;

public class UsePool {

public static ExecutorService executor;

public static void main(String args[])

{

Random random = new Random();

executor = Executors.newFixedThreadPool(1);

// Sum up wait times to know when to shutdown

int waitTime = 500;

for (int i = 0; i < 10; i++)

{

String name = "NamePrinter " + i;

int time = random.nextInt(1000);

waitTime += time;

Runnable runner = new NamePrinter(executor, name, time);

System.out.println("Adding: " + name + " / " + time);

executor.execute(runner);

}

try

{

Thread.sleep(waitTime);

executor.shutdown();

executor.awaitTermination(waitTime, TimeUnit.MILLISECONDS);

} catch (InterruptedException ignored) {

}

System.exit(0);

}

}

class NamePrinter implements Runnable {

private final String name;

private final int delay;

private final ExecutorService oExec;

public NamePrinter(ExecutorService oExec, String name, int delay)

{

this.oExec = oExec;

this.name = name;

this.delay = delay;

}

public void run()

{

System.out.println("Starting: " + name);

try {

Thread.sleep(delay);

} catch (InterruptedException ignored) {

System.out.println( ignored );

}

System.out.println("Done with: " + name);

if ( name.equals( "NamePrinter 9" ) )

oExec.execute( new NamePrinter(oExec, "Test1", 3000) );

else if ( name.equals( "Test1" ) )

oExec.execute( new NamePrinter(oExec, "Test2", 3000) );

}

}

It crashed when I tries to add Test2 (which is a child of a child of the root node):

Starting: NamePrinter 9

Done with: NamePrinter 9

Starting: Test1

Done with: Test1

Exception in thread "pool-1-thread-1" java.util.concurrent.RejectedExecutionException

at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1759)

at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:767)

at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:658)

at Sandbox.NamePrinter.run(NamePrinter.java:35)

at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)

at java.lang.Thread.run(Thread.java:619)

BigBadBurrowa at 2007-7-9 6:11:59 > top of Java-index,Java Essentials,Java Programming...