Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java reuse an executor

I work on a simulation system, where at each timestep, I have to simulate many models. I used a FixedThreadPool to speed up the calculation:

ExecutorService executor = Executors.newFixedThreadPool(nThread);
for (Model m : models) {
  executor.execute( m.simulationTask() );
}
executor.shutdown();
while ( ! executor.awaitTermination(10, TimeUnit.MINUTES) ) { 
  System.out.println("wait"); 
}

Now, the executor can't be used to execute() new Tasks after calling shutdown(). Is there a way to reset the executor, so I can reuse the existing executor (and its threads) at the next simulation step?

like image 319
daniel kullmann Avatar asked Jan 27 '12 15:01

daniel kullmann


People also ask

Can I reuse ExecutorService after shutdown?

After calling shutdown on a ExecutorService, no new Task will be accepted. This means you have to create a new ExecutorService for each round of tasks.

Can threads be reused?

Once a thread in the thread pool completes its task, it's returned to a queue of waiting threads. From this moment it can be reused. This reuse enables applications to avoid the cost of creating a new thread for each task. There is only one thread pool per process.

Is it necessary to shutdown ExecutorService?

When finished using an ExecutorService , you need to shut it down explicitly. From its javadoc: "An unused ExecutorService should be shut down to allow reclamation of its resources." Calling shutdown initiates a gradual and orderly shutdown.

Can we reuse threads in Java?

There is no "reuse" in this case. So it is true that you cannot call start() on a Java Thread twice but you can pass as many Runnable as you want to an executor and each Runnable 's run() method shall be called once.


3 Answers

You can reuse the executor service if you restructure your code somewhat.

Collection<Callable<Integer>> tasks = new ArrayList<Callable<Integer>>(16);
for (Model m : models) {
  tasks.add(m.simulationTask());
}

ExecutorService executor = Executors.newFixedThreadPool(nThread);
try {
  executor.invokeAll(tasks);
} catch(InterruptedException ie) {
  // Handle this
}

Basically you collect all your tasks, execute them, and await execution before proceeding. Of course, you could also alternatively just use a new Executor Service for each of your time steps, but at least you have options.

Caveats: I didn't compile the code so there might be errors. I also assumed an Integer parameter type for convenience.

like image 84
Perception Avatar answered Oct 28 '22 00:10

Perception


You can write your own implementation of the Executor interface. Beyond that, most of the default implementation that I am aware of reap threads and do memory cleanup after shutdown(), so there is no (to my knowledge) pre-made solution.

Considering that shutdown() is likely to do a lot of cleanup and garbage collection, it's not exactly clear why restarting would be better than accquiring a new Executor, perhaps you should look into the tutorials about extending ThreadPoolExecutor with a pause / resume set of methods instead of adding the ability to un-shutdown.

like image 40
Edwin Buck Avatar answered Oct 28 '22 01:10

Edwin Buck


Declare your ExecutorService as a member to your class and reuse it as you want. Do not call shutDown() on it as it will not accept any more tasks. Of course your tasks should end nicely and they also should terminate at some point.

like image 34
Alex Calugarescu Avatar answered Oct 28 '22 02:10

Alex Calugarescu