尝试测试我的一个类是否可以处理在多个线程上访问。我有一个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();
}
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<?>
存储在一些集合中,并在提交所有任务后运行断言。