我们试图在我们的应用程序的多线程部分和数据库访问之间实现一种保证,以便数据库不会受到太多线程(客户要求)的影响,同时保持系统的其他部分充分利用有必要数量的线程。
设计似乎可以工作(弹簧批处理分区+使用 ThreadPoolTaskExecutor 处理数据访问),但问题在于测试设计(基于http://helenaedelson.com/?p=432)。
现在,我必须将 Thread.sleep(4000) 添加到我的单元测试中,以确保在生成的额外线程发生更改以完成其工作并返回返回值之前,Spring 上下文不会从测试中被杀死到主线程。
有人会对如何使这个测试实现更智能有一些更好的想法吗?
测试者:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "classpath:partitionJdbcJob.xml" })
@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
public class TaskTests {
protected static final Logger logger = LoggerFactory.getLogger(TaskTests.class);
@Autowired
private OrderServiceImpl orderService;
@Test
public void testExecution() {
logger.info("Starting execution thread...");
for (int i = 0; i < 8; i++) {
orderService.dispatch();
}
try {
// So that spring context is not destroyed from under the multi-threaded runnables
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
测试服务:
@Service("orderServiceImpl")
public class OrderServiceImpl {
protected static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);
@Resource(name = "beanTaskExecutor")
private TaskExecutor taskExecutor;
// private AsyncTaskExecutor taskExecutor;
CompletionService completionService;
@Autowired
public void OrderServiceImpl(DataSource dataSource) {
completionService = new ExecutorCompletionService(taskExecutor);
}
public void dispatch(final RetailPriceOptimization order) {
logger.info("Starting dispatch execution...");
if (this.taskExecutor != null) {
logger.info("taskExecutor found...");
this.taskExecutor.execute(new Runnable() {
public void run() {
withExecutor(order);
}
});
}
try {
Object future1 = completionService.take().get();
Object future2 = completionService.take().get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
logger.info("Completed dispatch execution...");
}
private void withExecutor(final RetailPriceOptimization order) {
logger.info("Starting withExecutor execution...");
Object result1 = completionService.submit(new Callable<String>() {
public String call() {
return findById("0000dd2gsl1u1546");
}
});
Object result2 = completionService.submit(new Callable() {
public Object call() {
return orderDao.find(new Long("16"));
}
});
}
}