In my web application, I have a background service. This service uses Generator class that contains an Engine class and an ExecutorService
configured to use multiple threads and that accepts GeneratorTasks.
@Component
public class Generator {
@Autowired
private Engine heavyEngine;
private ExecutorService exec = Executors.newFixedThreadPool(3);
//I actually pass the singleton instance Generator class into the task.
public void submitTask(TaskModel model, TaskCallback callback) {
this.exec.submit(new GeneratorTask(model, this, callback));
}
}
@Component
public class Engine {
public Engine() {
//time-consuming initialization code here
}
}
public class GeneratorTask implements Callable<String> {
public GeneratorTask(TaskModel m, Generator g, ReceiptCallback c) {
this.m = m;
this.generator = g;
this.c = c;
}
public String call() throws Exception {
//This actually calls the Engine class of the generator.
//Maybe I should have passed the Engine itself?
this.generator.runEngine(c);
}
}
The Engine class takes a long time to initialize so I ideally want to initialize it only once per thread. I can't just make it a singleton instance because the instance can't be shared across multiple threads (it relies on sequential processing). It's perfectly fine to reuse the instance though, after a processing task has completed.
I was thinking of making the private Engine heavyEngine
variable a ThreadLocal variable. However, I'm also new to Spring so I was wondering if there might be another way to inject ThreadLocal variables using Spring annotations. I've looked at scoping the bean to request
scope, but I'm not sure how I should go about it given my design.
Any guidance on how to improve my design would be appreciated.