我正在尝试加速使用ExecutorService
并行运行任务的程序。它基本上是这样的:
初始化大小为n
阅读包含任务输入的一堆(约2500个文件)XML文件
使用池中的工作线程
一切都按预期工作,但我遇到的问题是每个工作线程都有一个类的实例,它对输入数据进行计算。此实例存储在ThreadLocal
中。现在,所有这些线程本地实例都是在对应工作线程启动时创建的,这意味着在读取所有XML输入文件之后。
由于计算对象的初始化需要相当长的时间,因此我宁愿让线程池从一开始就初始化所有工作线程,以便计算对象的初始化可以与读取输入文件并行运行。
这里有一些代码可以帮助您了解它当前的工作原理(我剥离了与问题无关的代码)。
初始化线程池和本地线程:
private final ExecutorService executor = Executors.newFixedThreadPool(Math.max(1, Runtime
.getRuntime().availableProcessors() - 1));
private ThreadLocal<Calculator> calculator = new ThreadLocal<Calculator>() {
@Override
protected Calculator initialValue() {
try {
Calculator instance = createCalculator();
return instance;
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
};
提交新计算:
@Override
public FutureTask<Output> calc(Input input) {
FutureTask<Output> task = new FutureTask<>(
new Callable<Rueckgabe>() {
@Override
public Output call() throws Exception {
try {
return calculator.get().calc(input);
} catch (Throwable e) {
System.err.println("Exception: " + e.getMessage());
e.printStackTrace(System.err);
return null;
}
}
});
executor.execute(task);
return task;
}
从一开始就让ExecutorService
从池中启动所有工作线程的正确方法是什么?或者我是否需要n
虚拟任务来强制初始化?
PS:由于IT限制,我必须在可预见的将来使用Java 7.
答案 0 :(得分:5)
将Threadfactory添加到将执行初始化的Executor。
executor = Executors.newFixedThreadPool(numprocrssors, new ThreadFactory ( ){
public Thread newThread(Runnable r) {
return new Thread(r){
{calculator.get();} // this is an initialization statement, added to all constructors.
};
}});