I have multiple runnable classes and I want to run them with executor service through a centralized class (call it Launcher class which contains list of all runnables).
I wrote a Launcher class which takes all the beans to instantiate using applicationContext.getBean(). Each runnable class also defines a pool size for it (number of threads to spawn for this runnable).
public class DaemonsLauncher {
@Autowired
private ApplicationContext appContext;
private List<Daemon> daemons = new ArrayList<Daemon>();
private ScheduledThreadPoolExecutor executor;
private void initThreadPool() throws Exception {
//daemonNames coming at run time from somewhere.
List<String> daemonList = Arrays.asList(daemonNames.split(Constant.COMMA));
//Pool size will now be summation of all the pool sizes.
int poolSize = 0;
for (String dName : daemonList) {
Daemon daemon = appContext.getBean(dName, Daemon.class);
poolSize += daemon.getPoolSize();
daemons.add(daemon);
}
executor = new ScheduledThreadPoolExecutor(poolSize);
}
public void launchDaemons() throws Exception {
for (Daemon daemon : daemons) {
for (int currentThreadCount = 1; currentThreadCount <= daemon.getPoolSize(); currentThreadCount++) {
executor.scheduleWithFixedDelay(daemon, 0, XYZ, ABC);
}
}
}
}
In the process of doing it, I add all runnables to a List<Daemon> (where Daemon is a abstract runnable class which is extended by other daemons).
public abstract class Daemon implements Runnable {
protected int poolSize = 1;
public int getPoolSize() {
return poolSize;
}
@Override
public void run() {
//Calls run methods of individual runnables here.
}
}
As you can see, I add same instance of each runnable class multiple times(depending on poolSize) while executing.
executor being a ScheduledThreadPoolExecutor.
The moment, run method of R is called, I find same instance of runnable class both the times since they were taken only once by appContext.getBean() (checked by printing hasCode and toString).
But these multiple instances of runnable class run at the same time.
What might be the issue with this sort of case? Are these multiple threads running for same runnable will cause issues or it will go fine?
As an alternative, depending on poolSize, I can get multiple instances of the Runnable class even before this loop and loop only once depending on all the ‘Runnable’ entries present in the List.
- All beans are prototype in nature (though it will not come into picture as I have called appContext.getBean only once).
-
A
sample Runnable class.public class R extends Daemon { @Override public void runIndividualDaemon() { //Called by run of Daemon class. logger.info("Running Daemon." + this.hashCode() + " " + this.toString()); } @Override protected void init() throws Exception { this.poolSize = 5; } }
If you have a task being performed multiple times, it is because you added it multiple times.
I suggest you log when you add tasks to confirm this.
A thread cannot perform two tasks at once, but it can perform one task after another, re-using the same thread.
I don’t believe add two tasks which are the same or adding the same task twice will make much difference in this case.