In the following class i'm using a SingleThreadPool (which is static) and i've made sure the static thread pool is initialized only once by using a Boolean object and making it synchronized(see init() method).I've made ThreadPoolExecutor static because i want to re-use the same pool across multiple incoming request.
This class has an inner class i.e) Validator which implements callable and returns a boolean.
The overridden submit method, iterates each input and submit the Validator(Task) to the ThreadPoolExecutor.
public class ValidationProcessor implements IValidation {
//should this be static or singleton
private static ThreadPoolExecutor executor;
private volatile static Boolean initialized= new Boolean(Boolean.FALSE);
List<Input> inputList;
public ValidationProcessor(List<Input> inputList) {
init();
this.inputList=inputList;
}
public static void init() {
try {
synchronized (initialized) {
if (!initialized.booleanValue()) {
LOG.debug("Initializing..................thread pool...");
final BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(1000);
executor = new ThreadPoolExecutor(3, 5, 60, TimeUnit.SECONDS,
queue);
initialized=new Boolean(Boolean.TRUE);
}
}
} catch (Exception e) {
LOG.error("Exception while initialising the thread pool {} and stack trace {}" , ExceptionUtils.getFullStackTrace(e));
}
}
public class Validator implements Callable<Boolean> {
private final Logger LOG = LoggerFactory.getLogger(Validator.class.getName());
Input input;
public ValidateNPublishTask(Input input) {
this.input=input;
}
public boolean validate() {
final Timer validateTimer = new Timer();
final boolean isValid = Validator.validate(input);//some process
return isValid;
}
@Override
public Boolean call() throws Exception {
return validate();
}
}
@Override
public boolean submit() {
Boolean consolidatedOutput=new Boolean(Boolean.TRUE);
List<Future<Boolean>> validationResult = new ArrayList<Future<Boolean>>();
try {
for (final Input i : inputs) {
Validator validate = new Validator(input);
Future<Boolean> r = getExecutor().submit(validate);
validationResult.add(r);
}
for (Future<Boolean> fr : validationResult) {
if (!fr.get()) {
//change consolidatedOutput to false;
break; // at-least one failure, return status as failure
}
}
} catch (InterruptedException | ExecutionException e) {
LOG.error("Exception while validating the input {} exception {}", ExceptionUtils.getFullStackTrace(e)});
}
return consolidatedOutput;
}
public static ThreadPoolExecutor getExecutor() {
return executor;
}
}
The above class is called from another class Processor.java as follows. This Processor is called within a Web-Application.Since, ValidationProcessor is local variable, it is thread safe.
Public Class Processor {
public Response process(Input input) {
List<Input> inputList = load();
IValidation validateNPublishObj = new ValidationProcessor(inputList);
emailResponse=validateNPublishObj.submit();
}
public List<Input> load() {
//return list of inputs <Input>
}
}
For simplicity sake, i've left some implementation empty like load().
My Question is more from a design perspective.
- In my ValidationProcessor class should the ThreadPoolExecutor be static or singleton.
/* sample singleton */
public class MyThreadPoolExecutor {
private final ThreadPoolExecutor executor;
private static MyThreadPoolExecutor threadPoolInstance = null;
private MyThreadPoolExecutor() {
executor = new ThreadPoolExecutor(...);
}
static {
threadPoolInstance = new MyThreadPoolExecutor();
}
public static MyThreadPoolExecutor getInstance() {
return threadPoolInstance;
}
}
- Does it make any difference if the instance variable of singleton rather than static(in the above case). My whole point is to use single thread pool, and i don't want to use/create a new ThreadPool for each incoming request.
Basically i want all my threads to use the same ThreadPoolExecutor and not to create a ThreadPoolExecutor instance everytime, when the instance of ValidationProcessor is created.
P.S: no need to verify the logic inside submit , assume that it compiles and works. Also the ThreadPoolExecutor is not shared across application and is used only in this class for now.