问题描述
我正在尝试加快使用并行运行任务的程序。 它基本上是这样的:
初始化大小为
n
的固定大小的线程池读取一堆(约2500个文件)包含任务输入的XML文件
使用池中的工作线程处理XML文件
一切都按预期工作,但是我的问题是每个工作线程都有一个对输入数据进行计算的类的实例。 该实例存储在 。 现在,所有这些线程本地实例都是在启动对应工作线程时创建的,这意味着在读取所有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。
1楼
将Threadfactory添加到执行器以执行初始化。
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.
};
}});