execute()以静默方式退出run()方法



尝试测试我的一个类是否可以处理在多个线程上访问。我有一个JUnit测试,在这个测试中我创建了一个类来实现Runnable并运行我的类。

当我运行execute时,它到达run((方法中的一行,然后在该线程上退出,而不报告任何问题,我已经用Try-Catch(Throwable(将其封装,但仍然没有出现问题的迹象。

这是我的代码:

class ConcurrencyTests {
class ConcurrentComponentTracker implements Runnable {
private String component;
ConcurrentComponentTracker(String component) {
this.component = component;
}
@Override
public void run() {
try {
System.out.printf("Component to track: [%s]n", component);
ParserHandler parserHandler = new ParserHandler();
System.out.println(parserHandler.componentTracker(component));
}
catch (Throwable t) {
t.printStackTrace();
}
}
}
@Test
void runRunner() {
ExecutorService executor = Executors.newFixedThreadPool(4);
String[] componentsToTrack = {"x", "y", "z"};
executor.execute(new ConcurrentComponentTracker(componentsToTrack[0]));
executor.execute(new ConcurrentComponentTracker(componentsToTrack[1]));
executor.execute(new ConcurrentComponentTracker(componentsToTrack[2]));
}
}

输出:

Component to track: [x]

Component to track: [y]

Component to track: [z]

它似乎只是在ParserHandler实例化行中退出,而没有报告任何内容。当尝试调试并进入该行时,它只是跳到最后,而不让我检查ParserHandler类实例化。

Whomever在一条评论中回答了问题,然后删除了它,这为我解决了问题。我的主JUnit线程没有等待其他线程完成。所以我把这些线钉到了最后,结果不出所料:

executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
}
catch (InterruptedException e) {
e.printStackTrace();
}
JUnit测试实际上应该测试并验证结果。在这种特殊的情况下,您的测试产生的输出应该由开发人员/测试人员进行验证,因此这不是自动化。我建议您使用Future<?>来跟踪任务执行的状态。对于Runnable任务,如果任务执行成功,Future<?>get()方法将返回null,否则它将向您转发用ExecutionException包装的异常。代码如下:
@Test
void runRunner() {
ExecutorService executor = Executors.newFixedThreadPool(3);
String[] componentsToTrack = {"x", "y", "z"};
assertNull(executor.submit(new ConcurrentComponentTracker(componentsToTrack[0]).get());
assertNull(executor.submit(new ConcurrentComponentTracker(componentsToTrack[1]).get());
assertNull(executor.submit(new ConcurrentComponentTracker(componentsToTrack[2]).get());
// cleanup and shutdown pool
executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
// ignore this
}
}

在执行此操作之前,您应该删除run()方法中的try/catch块。

您可能可以改进的另一件事是使executor成为测试类的一个字段,并使用@BeforeClass@Before。。。要进行初始化,请在测试之间进行清理,然后优雅地关闭池。请记住,从资源的角度来看,线程池并不那么便宜。

希望它能有所帮助!

p.S.如果您的目标是并行处理ConcurrentComponentTracker,那么您可以将Future<?>存储在一些集合中,并在提交所有任务后运行断言。

相关内容

  • 没有找到相关文章

最新更新