今天遇到了一个坑,也就是Junit写测试类的时候无法完成多线程的编写,之后简单的看了看源码,发现,Junit的确是不支持的
package superbook.utilTest;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.concurrent.ThreadLocalRandom;
import org.junit.Test;
import superbook.util.DBUtil;
public class DBUtilTest {
DBUtil dbUtil = new DBUtil();
@Test
public void getConnection() throws SQLException, InterruptedException {
System.out.println(dbUtil.getConnection());
Thread A = new Thread() {
@Override
public void run() {
try {
for(int i = 0; i<10; i++ ) {
Connection a = DBUtil.getConnection();
System.out.println(a);
System.out.println(i+"线程A获得Connection为: " + a);
}
}catch (Exception e) {
}
}
};
Thread B = new Thread() {
@Override
public void run() {
try {
for(int i = 0; i<100; i++ ) {
Connection a = dbUtil.getConnection();
System.out.println(i+"线程B获得Connection为: " + a);
}
}catch (Exception e) {
}
}
};
A.start();
B.start();
}
}
这是他的输出
jdbc:mysql://127.0.0.1:3306/superbook?userUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
com.mysql.cj.jdbc.ConnectionImpl@37f1104d
jdbc:mysql://127.0.0.1:3306/superbook?userUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
jdbc:mysql://127.0.0.1:3306/superbook?userUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
截取了部分源码
TestRunner源码
public static final int SUCCESS_EXIT = 0;
public static final int FAILURE_EXIT = 1;
public static final int EXCEPTION_EXIT = 2;
public static void main(String args[]) {
TestRunner aTestRunner = new TestRunner();
try {
TestResult r = aTestRunner.start(args);
if (!r.wasSuccessful())
System.exit(FAILURE_EXIT);
System.exit(SUCCESS_EXIT);
} catch (Exception e) {
System.err.println(e.getMessage());
System.exit(EXCEPTION_EXIT);
}
}
TestResult部分源码
protected List fFailures
protected List fErrors
public synchronized boolean wasSuccessful() {
return failureCount() == 0 && errorCount() == 0;
}
public synchronized int errorCount() {
return fErrors.size();
}
public synchronized int failureCount() {
return fFailures.size();
}
由上可以看出在TestRunner中,如果是单线程,当测试主线程执行结束后,不管子线程是否结束,都会回调TestResult的wasSuccessful方法,
然后判断结果是成功还是失败,最后调用相应的System.exit()方法。大家都知道这个方法是用来结束当前正在运行中的java虚拟机,那么线程也就都结束了
解决办法:
1 简单粗暴地让主线程休眠一段时间,然后让子线程能够运行结束。但是这个方法的弊端是,你不知道子线程的运行时间,所以需要看脸=_=
Thread.sleep();
2 使用CountDownLatch工具类,让主线程阻塞,直到子线程运行结束或者阻塞超时,这个方法要比第一个方法好点。
countDownLatch.await(5, TimeUnit.MINUTES);