[英]How to get ExecutorService or CompletionService to finish without asking for values of Futures?
We have some work to be done within a thread which will be run on a server for a web app using Spring Boot . 我们需要在一个线程中完成一些工作,该线程将使用Spring Boot在Web应用程序的服务器上运行。
What we want to happen is: 1) Work is submitted as our custom Runnable object 2) Work completes when it gets its turn (it's a database operation, and we don't need any return value except perhaps returning "Success" if the run() completed without exceptions) 我们想要发生的是:1)工作作为我们的自定义Runnable对象提交2)工作轮到它完成时(它是数据库操作,并且不需要任何返回值,除非运行即可返回“成功” ()已完成,无例外)
However, in our JUnit tests, it seems all the tasks submitted to an ExecutorService or CompletionService disappear when the main thread is finished, unless we call take() every time we add a new task (since it blocks until a task is finished, this makes tasks run sequentially, which defeats the purpose) or if we maintain a list of futures and call a method to loop through the list and get() the value of each feature. 但是,在我们的JUnit测试中,似乎主线程完成后,提交给ExecutorService或CompletionService的所有任务都会消失,除非每次添加新任务时都调用take()(因为它阻塞直到任务完成,所以这使任务按顺序运行(这会违背目的)),或者如果我们维护期货列表并调用一种方法来遍历列表并获取每个功能的值的方法。
The latter option we don't think is ideal because as a server application, we will have requests constantly coming in from different users and don't know how to detect when we should be clearing out the list of futures. 我们认为后一种选择不是理想的选择,因为作为服务器应用程序,我们将不断收到来自不同用户的请求,并且不知道如何检测何时应该清除期货清单。
Why do the threads silently disappear and what is a way around this? 为什么线程会静默消失,如何解决呢?
Don't run the code async: Just test the Runnable
directly: 不要异步运行代码:只需直接测试
Runnable
:
@Test
public void test() {
Runnable r = <your runnable>;
r.run();
// various assertions
}
It's pointless testing that your chosen ExecutorService
does its job - you can assume that. 您选择的
ExecutorService
完成其工作是毫无意义的测试-您可以假设这样做。
If you want to assert that your application is behaving correctly, use functional tests; 如果您想断言您的应用程序行为正确,请使用功能测试; ie, spin up a container (eg using
@SpringJUnit4ClassRunner
) with a hypersonic datasource, hit the spring boot end point then make you assertions about effect on the database. 即,使用超音速数据源启动一个容器(例如,使用
@SpringJUnit4ClassRunner
),击中spring boot的端点,然后使您断言对数据库的影响。
If you use spring boot's @Async
annotation for your service, you can even provide a configuration that uses a SynchronousTaskExecutor
so you don't have to pause in your test before making assertions. 如果您对服务使用spring boot的
@Async
批注,则甚至可以提供使用SynchronousTaskExecutor
的配置,因此您不必在断言之前暂停测试。
One good approach to testing async code is to block the main test thread and perform assertions in callbacks using something like ConcurrentUnit . 测试异步代码的一种好方法是使用ConcurrentUnit之类的方法阻塞主测试线程并在回调中执行断言。 Here's an example using a CompletableFuture's
whenComplete
callback: 这是一个使用CompletableFuture的
whenComplete
回调的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();
If either of the assertions in the callback thread fail, the test will fail as expected. 如果回调线程中的任何一个声明失败,则测试将按预期失败。 The main test thread will await a
resume
call before completing the test. 主测试线程将在完成测试之前等待
resume
调用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.