单元测试的代码是这样的,多线程访问数据库
public class B2BProductWriteManageImpl2Test extends BaseTest implements Runnable{
@Resource(name="b2BProductWriteManage2")
private B2BProductWriteManage2 b2BProductWriteManage2;
final Semaphore semp = new Semaphore(50);
@Test
public void addOrUpdateMpInfoWithTx() throws Exception {
B2BProductWriteManageImpl2Test b = new B2BProductWriteManageImpl2Test();
List<Thread> threads = new ArrayList<>();
for (int i=0; i< 50; i++) {
threads.add(new Thread(b));
}
for (Thread t : threads) {
t.start();
}
}
public void tt() throws Exception {
b2BProductWriteManage2 = SpringUtils.getBean("b2BProductWriteManage2");
for (int i= 0; i<50; i++) {
MerchantProductB2BDTO merchantProductB2BDTO = new MerchantProductB2BDTO();
merchantProductB2BDTO.setMpId(274340L);
merchantProductB2BDTO.setBarCode("6926892522052");
merchantProductB2BDTO.setMerchantId(-2L);
merchantProductB2BDTO.setMpCode("13231233");
merchantProductB2BDTO.setMpCode("1551");
merchantProductB2BDTO.setCompanyId(11L);
List<String> urls = new ArrayList<String>();
urls.add("http://test1.png");
urls.add("http://test2.png");
urls.add("http://test3.png");
urls.add("http://test4.png");
urls.add("http://test5.png");
merchantProductB2BDTO.setPicUrl(urls);
// 操作数据库
b2BProductWriteManage2.addOrUpdateMpInfoWithTx(merchantProductB2BDTO);
}
}
@Override
public void run() {
try {
semp.acquire();
System.out.println("current thread name:" + Thread.currentThread().getName());
tt();
semp.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}
然后就报了个Data source is closed的错。
org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is java.sql.SQLException: Data source is closed
查资料说是junit不支持多线程单元测试,因为源码里面有个System.exit();
猜测是junit运行单元测试的时候会将当前线程作为主线程,主线程运行结束后退出,会引起其他子线程强制退出。
Semaphore信号量的本意是增大并发的可能。
最后加了个CountDownLatch解决了主线程退出的问题。
public class B2BProductWriteManageImpl2Test extends BaseTest implements Runnable{
@Resource(name="b2BProductWriteManage2")
private B2BProductWriteManage2 b2BProductWriteManage2;
static final int clientCount = 100;
final Semaphore semp = new Semaphore(clientCount);
CountDownLatch latch = new CountDownLatch(clientCount);
private static final Logger log = LoggerFactory.getLogger(B2BProductWriteManageImpl2Test.class);
@Test
public void addOrUpdateMpInfoWithTx2() throws Exception {
MerchantProductB2BDTO merchantProductB2BDTO = new MerchantProductB2BDTO();
merchantProductB2BDTO.setMpId(274340L);
merchantProductB2BDTO.setBarCode("6926892522052");
merchantProductB2BDTO.setMerchantId(-2L);
merchantProductB2BDTO.setMpCode("13231233");
merchantProductB2BDTO.setMpCode("1551");
merchantProductB2BDTO.setCompanyId(11L);
merchantProductB2BDTO.setAppId(1+"");
List<String> urls = new ArrayList<String>();
urls.add("http://test1.png");
urls.add("http://test2.png");
urls.add("http://test3.png");
urls.add("http://test4.png");
urls.add("http://test5.png");
merchantProductB2BDTO.setPicUrl(urls);
//
log.info("current thread name:" + Thread.currentThread().getName() + ":" + 1);
b2BProductWriteManage2.addOrUpdateMpInfoWithTx(merchantProductB2BDTO);
}
@Test
public void addOrUpdateMpInfoWithTx() throws Exception {
B2BProductWriteManageImpl2Test b = new B2BProductWriteManageImpl2Test();
List<Thread> threads = new ArrayList<>();
for (int i=0; i< clientCount; i++) {
threads.add(new Thread(b));
}
for (Thread t : threads) {
t.start();
}
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void tt() throws Exception {
b2BProductWriteManage2 = SpringUtils.getBean("b2BProductWriteManage2");
for (int i= 0; i<clientCount; i++) {
final int index = i;
MerchantProductB2BDTO merchantProductB2BDTO = new MerchantProductB2BDTO();
merchantProductB2BDTO.setMpId(274340L);
merchantProductB2BDTO.setBarCode("6926892522052");
merchantProductB2BDTO.setMerchantId(-2L);
merchantProductB2BDTO.setMpCode("13231233");
merchantProductB2BDTO.setMpCode("1551");
merchantProductB2BDTO.setCompanyId(11L);
merchantProductB2BDTO.setAppId(index+"");
List<String> urls = new ArrayList<String>();
urls.add("http://test1.png");
urls.add("http://test2.png");
urls.add("http://test3.png");
urls.add("http://test4.png");
urls.add("http://test5.png");
merchantProductB2BDTO.setPicUrl(urls);
//
log.info("current thread name:" + Thread.currentThread().getName() + ":" + index);
b2BProductWriteManage2.addOrUpdateMpInfoWithTx(merchantProductB2BDTO);
}
}
@Override
public void run() {
try {
semp.acquire();
tt();
semp.release();
} catch (Exception e) {
e.printStackTrace();
}
}