java重用执行器
我在一个模拟系统上工作,在每个时间步,我必须模拟许多模型。我使用FixedThreadPool来加速计算:java重用执行器,java,multithreading,concurrent-programming,java.util.concurrent,Java,Multithreading,Concurrent Programming,Java.util.concurrent,我在一个模拟系统上工作,在每个时间步,我必须模拟许多模型。我使用FixedThreadPool来加速计算: ExecutorService executor = Executors.newFixedThreadPool(nThread); for (Model m : models) { executor.execute( m.simulationTask() ); } executor.shutdown(); while ( ! executor.awaitTermination(10,
ExecutorService executor = Executors.newFixedThreadPool(nThread);
for (Model m : models) {
executor.execute( m.simulationTask() );
}
executor.shutdown();
while ( ! executor.awaitTermination(10, TimeUnit.MINUTES) ) {
System.out.println("wait");
}
现在,在调用
shutdown()
之后,执行器不能用于execute()
新任务。有没有办法重置执行器,以便我可以在下一个模拟步骤中重用现有的执行器(及其线程)?您可以编写自己的执行器接口实现。除此之外,我知道的大多数默认实现都是在shutdown()
之后收获线程并进行内存清理,因此(据我所知)没有预先制定的解决方案
考虑到shutdown()
可能会进行大量清理和垃圾收集,现在还不清楚为什么重新启动会比使用新的执行器更好,也许您应该查看教程,而不是添加取消关机的功能。只需获取另一个执行器服务即可。无论如何,开销是最小的
如果您坚持重用相同的执行器,您可以实现自己的屏障机制。在提交新任务时,以原子方式递增计数器。任务完成后,按原子顺序递减计数器。在主线程中,等待计数器为零。比如:
// globally visible objects
AtomicInteger counter = new AtomicInteger(0);
Object signal = new Object();
ExecutorService executor = Executors.newFixedThreadPool(nThread);
for (Model m : models) {
counter.getAndIncrement();
executor.execute( m.simulationTask() );
}
synchronized(signal) {
while(count.get() > 0) {
signal.wait();
}
}
然后在任务的运行:
public void run() {
// original code
// at the end:
synchronized(signal) {
counter.getAndDecrement();
signal.notify();
}
}
如果稍微重新构造代码,则可以重用executor服务
Collection<Callable<Integer>> tasks = new ArrayList<Callable<Integer>>(16);
for (Model m : models) {
tasks.add(m.simulationTask());
}
ExecutorService executor = Executors.newFixedThreadPool(nThread);
try {
executor.invokeAll(tasks);
} catch(InterruptedException ie) {
// Handle this
}
Collection tasks=newarraylist(16);
适用于(型号m:型号){
tasks.add(m.simulationTask());
}
ExecutorService executor=Executors.newFixedThreadPool(nThread);
试一试{
执行人。调用所有(任务);
}捕获(中断异常ie){
//处理这个
}
基本上,您收集所有任务,执行它们,并在继续之前等待执行。当然,您也可以为每个时间步使用新的Executor服务,但至少您有选择
注意事项:我没有编译代码,因此可能会出现错误。为了方便起见,我还假设了整数参数类型。将您的声明为类的成员,并根据需要重用它。不要对其调用shutDown(),因为它将不再接受任何任务。当然,您的任务应该很好地结束,它们也应该在某个时刻终止。我不会说创建一个线程池支持的执行器的开销最小……这取决于他使用了多少线程。如果这个数字很小,那么就没有多少开销。此外,如果他正在执行的任务是粗粒度的,那么相对于应用程序的其余部分来说,它是可以忽略不计的。在进入下一步之前,您还没有演示如何等待所有任务完成。@dogbane-invokeAll
等待所有任务完成。因为他正在使用execute(Runnable)
它不返回值,我们可以选择可调用的
也许?@mzzzzb-我通常喜欢假设某种返回类型,但是的,他肯定可以。