我有一个要在文件上完成的任务管道,每种不同类型的任务都在不同的执行程序服务中运行。在初始化每个执行程序服务后,我开始第一个任务,这保证在完成处理所有文件之前不会完成,因为它处理一个文件夹,要么不需要更多工作,要么它向 service2 提交一个可调用的任务。因此,当第一个任务的 shutdown() 调用成功时,所有文件现在都将在 task2 中处理,或者在流水线下游的另一个任务中处理,依此类推。当我们可以关闭最终服务时,我们就完成了。
Loader loader = Loader.getInstanceOf();
List<ExecutorService> services = new ArrayList<ExecutorService>();
ExecutorService es = Executors.newSingleThreadExecutor();
//Init Services
services.add(es);
services.add(task1.getService());
services.add(task2.getService());
services.add(task3.getService());
services.add(task4.getService());
//Start Loading Files
es.submit(loader);
int count = 0;
for (ExecutorService service : services)
{
service.shutdown();
count++;
//Now wait for all submitted tasks to complete, for upto one day per task
service.awaitTermination(10, TimeUnit.DAYS);
MainWindow.logger.severe("Shutdown Task:" + count);
}
public class AnalyserService
{
protected String threadGroup;
public AnalyserService(String threadGroup)
{
this.threadGroup=threadGroup;
}
protected ExecutorService executorService;
protected CompletionService completionService;
protected void initExecutorService()
{
int workerSize = Runtime.getRuntime().availableProcessors();
executorService
= Executors.newFixedThreadPool(workerSize, new SongKongThreadFactory(threadGroup));
}
public ExecutorService getService()
{
if (executorService == null || executorService.isShutdown())
{
initExecutorService();
}
return executorService;
}
}
所以这一切都很好,除了我的 cpu 加载逻辑不正确。每个服务都使用与计算机拥有的 CPU 数量相等的池。因此,如果计算机有 4 个 CPU,而我们有 5 个服务,那么我们可以有 20 个线程同时尝试工作,从而使 CPU 过载。我想在这种情况下我应该一次只有 4 个线程。
如果我将每个服务限制为使用一个线程,那么 ID 只有 5 个线程同时运行,但这仍然不正确,因为
- 如果有更多的服务或更多的 CPU 将不再正确
- 效率低下,因为大部分工作的流水线将由 task1 完成,如果我将其限制为一个 cpu,它将比必要的慢,相反,稍后大多数线程将由以后的任务完成,而 task1 将一无所有去做。
我认为我需要让所有任务共享一个执行器服务,并将其池大小设置为等于计算机拥有的 cput 数量。但是,我将如何确定服务何时完成?
我正在使用 Java 7,那么 Java 7 中的新功能是否有帮助,目前只使用 Java 5 并发特性