迁移异步任务执行程序以使用链接的CompletableFuture

时间:2017-09-19 13:00:33

标签: java multithreading executorservice completable-future

我有一个异步任务处理器,我希望迁移到使用新的CompletableFuture语法,因为这最初似乎是一种更自然的方式来管理我的任务依赖关系,我找不到的关于CompletableFuture的指南都没有覆盖我的案例,所以我正在寻找一些关于最佳方法的建议:

  • 这是一个命令行应用程序,用户提供任务列表,然后等待它们完成。
  • 任务列表大约有50个任务,可以对数据库进行各种数据导入。
  • 这些任务都会返回一个导入报告,其中包含时间摘要报告,已处理的数据等...以便输出给用户。
  • 虽然有些任务没有依赖关系,但大部分任务都依赖于完成的一个或多个其他任务(其中更多是任意数字,最有可能是2-3,但有时高达10-15)。
  • 如果任务依赖于其他任务,则始终要求完成所有这些任务(所以CompletableFuture.allOf)。
  • 如果任务依赖于其他任务,它永远不会依赖于返回的导入报告,只取决于数据库状态,因此不需要使用前一个Future的结果。
  • 部分任务耗时很长
  • 当用户在等待时,我想经常输出一些状态,让他们知道它仍在运行。
  • 由于各种原因,任务可能会因异常而失败,无异常=成功。
  • 如果任务失败,我需要停止执行相关任务
  • 如果任务失败,我想停止执行任何新任务,理想情况下让当前任务运行完成,然后关闭。

当前实现使用ThreadPoolExecutor和ExecutorCompletionService:

  1. 构建所有任务的依赖关系树
  2. 提交所有没有依赖关系的任务
  3. 流量控制代码在AtomicInteger正在进行的CompletionService.poll(timeout)个任务中循环调用Future.get()
  4. 如果它获得完成的任务,则调用Executor.shutdownNow()来收集报告,然后运行一些依赖关系管理代码,以将任何现在未被阻止的任务添加到执行程序。 (并妥善管理正在进行的任务的数量)。
  5. 如果多次民意调查没有完成,则会向用户输出一条消息。 (并且有一些超时和放弃代码,但基本相同)
  6. 如果future.get()中发生异常,则调用CompletableFuture清除队列并停止任何进一步的任务,输出结果,它有一个尽可能有用的错误消息。
  7. 当正在进行的任务数量达到0时,主控制循环结束,代码执行整齐关闭并为用户输出有关其任务执行情况的报告。

    缺点是存在大量的样板,管理轮询,异常处理和提交相关的依赖项,依赖管理器和执行程序紧密耦合。

    表面CompletableFuture.supplyAsync()似乎非常有用。构建了依赖关系树并对其进行了排序后,我可以迭代树并使用CompletableFuture.allOf()来执行没有依赖关系的任务,当我使用依赖关系执行任务时使用CompletableFuture<Report>[] dependencies = getBlockingTasks(task); CompletableFuture<Void> allOf = CompletableFuture.allOf(dependencies); CompletableFuture<Report> future = allOf.thenApplyAsync(v -> executeTask(task)), threadPoolExecutor);

    thenApply

    我也可以使用thenAcceptCompletableFuture<Void> allOf = CompletableFuture.allOf(allMyTasks); allOf.join(); 链接到每个工作线程处理报告并记录它。

    我不确定的主要区域是异常处理和轮询/等待。如果我不想在需要花费一些时间的时候提供更新,我会使用:

    import numpy as np 
    import theano 
    import theano.tensor as T 
    
    a = T.scalar('a')
    b = T.scalar('b')
    w = theano.shared(value = 1., name='w')
    c = a * w + b
    f = theano.function([a,b], c)
    theano.printing.pydotprint(f, outfile="_f.png", var_with_name_simple=True)
    
    x1 = T.scalar('x1')
    x2 = T.scalar('x2')
    y1 = theano.clone(c, replace={a:x1})
    y2 = theano.clone(c, replace={a:x2})
    
    y = y1 + y2
    
    g = theano.function([x1,x2, b], y)
    theano.printing.pydotprint(g, outfile="_g.png", var_with_name_simple=True)
    
    print(g(1,2,3)) # print 9 
    

    我不确定管理异常处理的最佳方法。

    所以(除了我发布的敏感片段之外),我能够跟踪我的任务完成状态的最佳方式是什么,所以如果事情正在进行,我可以继续向用户输出内容有一段时间,管理异常的最佳方法是什么,也许重要的是,这实际上是一种明智的模式,还是我被新的和闪亮的东西所吸引,做了一些我想要的事情&#34;?< / p>

0 个答案:

没有答案