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?
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.
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.
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With