如何在不询问期货价值的情况下完成ExecutorService或CompletionService?

时间:2015-06-29 14:34:38

标签: java concurrency executorservice

我们在一个线程中有一些工作要做,这个线程将在使用Spring Boot的Web应用程序的服务器上运行。

我们想要发生的是: 1)工作作为我们的自定义Runnable对象提交 2)工作在轮到它时完成(这是一个数据库操作,我们不需要任何返回值,除非在没有异常的情况下run()完成后返回“Success”)

然而,在我们的JUnit测试中,似乎提交给ExecutorService或CompletionService的所有任务在主线程完成时消失,除非我们每次添加新任务时调用take()(因为它会阻塞直到任务是完成后,这会使任务按顺序运行,这会破坏目的)或者如果我们维护一个期货列表并调用一个循环遍历列表的方法并获取()每个特征的值。

我们认为后一种选择并不理想,因为作为服务器应用程序,我们会不断地向不同用户发出请求,并且不知道如何检测何时应该清除期货列表。

为什么线程会默默地消失,这是怎么回事?

2 个答案:

答案 0 :(得分:1)

不要运行代码异步:直接测试@Test public void test() { Runnable r = <your runnable>; r.run(); // various assertions }

ExecutorService

毫无意义的测试表明,您所选择的@SpringJUnit4ClassRunner能够胜任其工作 - 您可以认为。

如果要断言应用程序的行为正确,请使用功能测试;即,使用高超音速数据源旋转容器(例如使用@Async),点击弹簧启动终点然后让你断言对数据库的影响。

如果您为服务使用春季启动SynchronousTaskExecutor注释,您甚至可以提供使用dv.RowFilter = "(FirstName like '%" + textBox1.Text + "%'" + " OR LastName like '%" + textBox1.Text + "%') AND Checked = 1"; 的配置,这样您就不必在测试之前暂停做断言。

答案 1 :(得分:0)

测试异步代码的一个好方法是阻止主测试线程并使用ConcurrentUnit之类的东西在回调中执行断言。以下是使用CompletableFuture的whenComplete回调的示例:

Waiter waiter = new Waiter();

CompletableFuture<Connection> future = someService.connect();
future.whenComplete((connection, failure) -> {
  // Called from some other thread
  waiter.assertNotNull(connection);
  waiter.assertNull(failure);
  waiter.resume();
});

// Block the main test thread
waiter.await();

如果回调线程中的任何一个断言失败,则测试将按预期失败。在完成测试之前,主测试线程将等待resume调用。