1:上一篇博文,介绍了Synchronized 和 配合Spring @Transtaction使用。下面咱们做一个测试。
2:在做并发测试前,可以预先设计使用线程池的execute方法、还是submit,虽然submit方法最后还是调用了线程池的execute;但submit方法封装了一个返回Future的值。
3:测试代码
public class MultiThreadTestCase extends AbstractSpringContextTestSupport {
@Autowired
SynchronizedNoTransService synchronizedNoTransService;
@Autowired
SynchronizedService synchronizedService;
@Test
public void testUpdateBalance() throws Exception {
int threadCount = 2;
ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
List<Future<Integer>> futures = new ArrayList<Future<Integer>>();
for (int x = 0; x < threadCount; x++) {
Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
synchronizedService.synMethodTwo();
return 1;
}
};
Future<Integer> submit = executorService.submit(callable);
futures.add(submit);
}
List<Exception> exceptions = new ArrayList<Exception>();
for (Future<Integer> future : futures) {
try {
future.get();
} catch (Exception e) {
exceptions.add(e);
e.printStackTrace(System.err);
}
}
}
}
SynchronizedService中synMethodTwo的方法,业务逻辑处理最后是更新账户信息;此时会出现并发可能。
(1)相同的数据并发更新。
可以考虑同步方法设计。
(2)不同的数据并发更新
不同数据并发更新账户信息,由于Spring data jpa 维护了version 版本的信息,在遍历线程池submit返回的Future,future.get()方法时,可以看到Console信息两个异常信息,StaleObjectStateException和ObjectOptimisticLockingFailureException异常信息。
该问题的解决方法,可能要从业务设计上或者多任务并发编程上下点功夫,目前我还对这种高并发没有策略。