1

我有一个要在文件上完成的任务管道,每种不同类型的任务都在不同的执行程序服务中运行。在初始化每个执行程序服务后,我开始第一个任务,这保证在完成处理所有文件之前不会完成,因为它处理一个文件夹,要么不需要更多工作,要么它向 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 个线程同时运行,但这仍然不正确,因为

  1. 如果有更多的服务或更多的 CPU 将不再正确
  2. 效率低下,因为大部分工作的流水线将由 task1 完成,如果我将其限制为一个 cpu,它将比必要的慢,相反,稍后大多数线程将由以后的任务完成,而 task1 将一无所有去做。

我认为我需要让所有任务共享一个执行器服务,并将其池大小设置为等于计算机拥有的 cput 数量。但是,我将如何确定服务何时完成

我正在使用 Java 7,那么 Java 7 中的新功能是否有帮助,目前只使用 Java 5 并发特性

4

1 回答 1

-1

您问题的核心是:“[...] 使 CPU 过载。” 如果这是问题所在,只需正确安排应用程序的优先级即可。顺便说一句,你更有可能增加 IO 负载而不是增加 CPU 负载;很多不同的线程实际上是一件好事:-)

但是,您的问题是:“但是我将如何确定服务何时完成?” 非常简单的答案:submit()而不是invokeAll()检查您收到isDone()的对象的方法。Future

http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorService.html#submit(java.util.concurrent.Callable )

于 2012-10-17T10:44:44.610 回答