Java 如何在junit中为多线程测试使用未捕获的异常处理程序?
我有下面的代码,我希望能够成功运行到完成,但是代码在“fail”(“this should not reach”);”行失败。有人能解释一下为什么不调用默认的未捕获异常处理程序吗:Java 如何在junit中为多线程测试使用未捕获的异常处理程序?,java,multithreading,junit,Java,Multithreading,Junit,我有下面的代码,我希望能够成功运行到完成,但是代码在“fail”(“this should not reach”);”行失败。有人能解释一下为什么不调用默认的未捕获异常处理程序吗: public class UncaughtExceptionTest extends TestCase implements UncaughtExceptionHandler { private final List<Throwable> uncaughtExceptions =
public class UncaughtExceptionTest extends TestCase
implements UncaughtExceptionHandler {
private final List<Throwable> uncaughtExceptions =
new CopyOnWriteArrayList<Throwable>();
class UncaughtExceptionTestInnerClass implements Runnable {
private final ScheduledThreadPoolExecutor executor =
new ScheduledThreadPoolExecutor(1);
private final CountDownLatch latch;
UncaughtExceptionTestInnerClass(CountDownLatch latch) {
this.latch = latch;
executor.schedule(this, 50, TimeUnit.MILLISECONDS);
}
@Override
public void run() {
System.out.println("This is printed");
fail("this should fail");
latch.countDown();
}
}
@Test
public void testUncaughtExceptions() {
Thread.setDefaultUncaughtExceptionHandler(this);
CountDownLatch latch = new CountDownLatch(1);
UncaughtExceptionTestInnerClass testTheInnerClass =
new UncaughtExceptionTestInnerClass(latch);
try {
if (!latch.await(1, TimeUnit.SECONDS)) {
if (uncaughtExceptions.size() > 0) {
Throwable exception = uncaughtExceptions.get(0);
System.out.println("First uncaught exception: " +
exception.getMessage());
}
else {
fail("this should not be reached");
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void uncaughtException(Thread t, Throwable e) {
uncaughtExceptions.add(e);
}
}
公共类UncaughtExceptionTest扩展了TestCase
实现UncaughtExceptionHandler{
私有最终列表未捕获异常=
新建CopyOnWriteArrayList();
类UncaughtExceptionTestInerClass实现Runnable{
私有最终调度线程池执行器执行器=
新的ScheduledThreadPoolExecutor(1);
私有最终倒计时闩锁;
UncaughtExceptionTestInReclass(倒计时闩锁闩锁){
this.latch=闩锁;
执行者计划(这个,50,时间单位为毫秒);
}
@凌驾
公开募捐{
System.out.println(“已打印”);
失败(“本应失败”);
倒计时();
}
}
@试验
public void testUncaughtExceptions(){
setDefaultUncaughtExceptionHandler(this);
CountDownLatch闩锁=新的CountDownLatch(1);
UncaughtExceptionTestInReclass测试InReclass=
新的UncaughtExceptionTestInnerClass(闩锁);
试一试{
如果(!闩锁等待(1,时间单位秒)){
如果(uncaughtExceptions.size()>0){
Throwable exception=uncaughtExceptions.get(0);
System.out.println(“第一个未捕获的异常:”+
异常。getMessage());
}
否则{
失败(“不应达到此目标”);
}
}
}捕捉(中断异常e){
e、 printStackTrace();
}
}
@凌驾
公共无效未捕获异常(线程t,可丢弃的e){
添加(e);
}
}
这与您正在使用执行器运行任务有关。只有当线程由于未捕获异常即将终止时,才会调用未捕获异常处理程序。如果您将实现更改为使用普通线程,以便线程将以异常终止,您将看到预期的行为
根据您提交任务的方式,executor线程可能会捕获并处理所有丢弃的任务。因此,线程不会因为这些异常而终止,因此未捕获的异常处理程序不会参与其中。例如,ThreadPoolExecutor.execute(Runnable)将触发未捕获异常处理程序。但是,ThreadPoolExecutor.submit(可调用)不会。另外,ScheduledThreadPoolExecutor.schedule()也没有(这与它们使用FutureTask实现有关)
使用executor服务访问意外异常的更好方法是通过Future
ScheduledThreadPoolExecutor。schedule()
采用可运行的/可调用的参数,而不是线程。前者没有运行时异常处理程序。在run
或call
方法中为RuntimeException
设置一个try
/catch
块。为什么失败(“这应该失败”)代码>行吗?这是故意的吗?这样门闩就不会倒计时了。@BalusC:是的,这是故意的。为了正确地通过测试,lock.await()方法应该超时,从而使其返回false。然后,代码应该打印来自在您询问的行上抛出的未捕获断言FailedError异常的消息。