我在我的Web应用程序中有一个后台服务。该服务使用Generator类,该类包含Engine类和配置为使用多个线程并接受GeneratorTasks的ExecutorService。
@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);
}
}
Engine类初始化时间较长,因此我希望每个线程只初始化一次。但是我不能将其作为单例实例,因为该实例无法在多个线程之间共享(它依赖于顺序处理)。在处理任务完成后,重用该实例是完全可以的。
我考虑将私有变量
heavyEngine
设置为ThreadLocal变量。然而,我对Spring也不太熟悉,所以我想知道是否有另一种使用Spring注解注入ThreadLocal变量的方法。我已经尝试将bean的作用域设置为request
,但是鉴于我的设计,我不确定应该如何操作。如果能提供任何改进设计的指导,我将不胜感激。
Engine
被自动装载(Autowired),我假设您已经将其声明为一个 Bean。默认情况下,Spring 的 Bean 是单例的,因此很有可能您的Engine
已经是一个单例了。 - a.b.dsingleThreadExecutor
,所以我不会遇到任何并发问题。我只是在寻找其他实现类似ThreadLocal行为的方法。=) - Jensen Ching