当前位置: 首页 > 面试题库 >

将ExecutorService与任务树结合使用以执行

姜鹏程
2023-03-14
问题内容

我们有一个问题。:)

我们要确保任何时候只有N个线程在执行后台任务。为此,我们使用了固定线程池执行程序。它似乎工作正常。

然后我们发现了一个问题。假设您有一个使用执行程序执行一些并行工作的类,然后在执行程序线程中调用了另一个类,该线程也执行一些并行工作,打算等待它。这是发生了什么:

  • 主线程调用第一级方法。
  • 这种方法认为它可以并行化为16个任务,并拆分其工作。
  • 16个任务被提交给执行者。
  • 主线程开始等待其任务完成。
  • 假设有四个线程可用,则每个前四个任务都会被拾取并运行。因此,队列中还有12个任务。
  • 现在,这些任务之一调用了其他方法。
  • 这种新方法认为它可以并行化为2个任务。假设这是并行合并排序中的第一步,或者类似的东西。
  • 2个任务被提交给执行者。
  • 现在,该线程开始等待其任务完成。

哦哦 因此,此时,所有四个线程将等待任务完成,但是它们正在协作阻止实际执行这些任务的执行程序。

此问题的解决方案1如下:在向执行程序提交新任务时,如果我们已经在运行所有线程,并且已经在其中一个执行程序线程上运行,则内联运行任务。这可以正常工作10个月,但是现在我们遇到了问题。如果它正在提交的新任务还比较大,那么您可能会遇到新任务阻止该方法将其他任务添加到队列的情况,否则其他线程就可以将其拾取。因此,在线程内联处理工作时,您会遇到巨大的延迟。

有没有更好的解决方案来解决执行潜在无限制的后台任务树这一核心问题?我知道,.NET相当于执行程序服务,具有某种内置的从队列中窃取的功能,可以防止发生原始的死锁问题,据我所知,这是一个理想的解决方案。但是在Java领域呢?


问题答案:

Java
7的概念ForkJoinPool允许任务通过将任务提交给同一执行者来“分叉”另一个任务。然后为它提供一个选项,供以后尝试通过尝试运行“帮助加入”该任务(如果尚未运行)的选项提供。

我相信,通过简单地将Executorwith与组合,可以在Java 6中完成相同的操作FutureTask。像这样:

public class Fib implements Callable<Integer> {
    int n;
    Executor exec;

    Fib(final int n, final Executor exec) {
        this.n = n;
        this.exec = exec;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Integer call() throws Exception {
        if (n == 0 || n == 1) {
            return n;
        }

        //Divide the problem
        final Fib n1 = new Fib(n - 1, exec);
        final Fib n2 = new Fib(n - 2, exec);

        //FutureTask only allows run to complete once
        final FutureTask<Integer> n2Task = new FutureTask<Integer>(n2);
        //Ask the Executor for help
        exec.execute(n2Task);

        //Do half the work ourselves
        final int partialResult = n1.call();

        //Do the other half of the work if the Executor hasn't
        n2Task.run();

        //Return the combined result
        return partialResult + n2Task.get();
    }

}


 类似资料:
  • 我使用java.util.concurrent.ExecutorService和固定线程池来执行任务列表。我的任务列表通常在80-150个左右,我已经将任何时候运行的线程数限制为10个,如下所示: 我的用例要求即使完成的任务也应该重新提交给ExecutorService,但是只有当所有已经提交的任务都被服务/完成时,才应该再次执行/获取。也就是说,提交的任务基本上应该轮流执行。因此,在这种情况下不

  • 要并行或异步运行一些东西,我可以使用ExecutorService:

  • 问题内容: 快速回顾一下-我有一个Java EE前端,可以接受用户请求,然后针对每个请求使用ExecutorService(SingleThreadedExecutor设置为守护程序)启动冗长的工作流,该工作流包含在库中并且可以工作很好,并且在通过Eclipse以独立模式运行时按预期运行。当从website(servlet)调用时,我观察到工作流始终在初始化Velocity Engine(Velo

  • 我已经使用ExecutorService实现了超时任务。在下面的方法中,我正在提交超时任务,如果它在给定的时间内超时,我将取消该任务并关闭执行器。 它运行得很好,我没有任何问题。 然而,我想知道这是否是最好的代码设计。我只是想知道如果使用ExecutorService返回的未来是否会更好。submit()获取可调用函数的返回值或超时超时任务。例如 我正在使用JDK7。

  • 问题内容: 我有三个连接的线程,即第二个线程在第一个死后执行。 这是我的代码: 我将如何使用而不是三个线程对象来实现此功能? 问题答案: 如果您想要/需要的是一个接一个地执行一组作业,但要在与主应用程序线程不同的单个线程中执行,请使用。

  • 问题内容: 我使用带有固定线程池的java.util.concurrent.ExecutorService执行任务列表。我的任务列表通常约为80-150,并且我将随时运行的线程数限制为10,如下所示: 我的用例要求即使完成的任务也应重新提交给 ExecutorService, 但只有在服务/完成所有 已 提交的任务后才应再次执行/采用。基本上,提交的任务应以轮换为基础执行。因此,在这种情况下不会有