我使用Grails通过线程池实现多线程进程,每个线程创建并保存域对象Microblog。但似乎只要在任何线程中发生异常,线程池就会被关闭。在我的例子中, org.springframework.dao.DataIntegrityViolationException 导致 java.util.concurrent.ExecutionException ,随后终止我的线程池和所有后续逻辑。
我不希望这种情况发生,所以我想在保存域对象时捕获所有可能的spring和hibernate异常。简而言之,我想知道如何在Spring和Hibernate的框架下捕获可能的异常。
我的多线程是这样的:
ExecutorService es = Executors.newFixedThreadPool(threadCount);
def threads=[];
for(int i=0;i<threadCount;i++){
threads.add(new MyThread(params));
}
try {
//submit all threads to the pool
List<Future> futures = threads.collect{theThread->
es.submit({->
theThread.run();
});
}
futures.each{it.get()}
}finally {
def notRun=es.shutdownNow();
log.info "Now the thread pool is shut down. Still ${notRun} threads are not finished and stopped.";
}
在已实现的runnable类中:
public MyThread implements Runnable{
@Override
public void run(){
//some logic here
Microblog.withTransaction{
Microblog m=new Microblog(some params);
try{
m.save(flush:true);
if(m.hasErrors()){log.error m.errors}
}catch(//how to catch spring and hibernate exceptions in one catch?){//Some error handling here. At least the thread lives.
}
}
}
}
欣赏你富有洞察力的想法!
答案 0 :(得分:1)
尝试使用ThreadGroup.uncaughtException和/或Thread.UncaughtExceptionHandler。
在你的catch块中,你可以捕获所有异常,然后检查它是否是休眠或像春天一样:
catch(Exception e) {
if(e.getClass().getCanonicalName().beginsWith("org.springframework")) {
}
if(e.getClass().getCanonicalName().beginsWith("org.springframework")) {
}
}
其他选项是检查异常类是否是Spring / Hibernate的BaseException接口。 Spring没有它,但您可以尝试org.springframework.core.NestedRuntimeException。对于Hibernate,您可以使用org.springframework.core.NestedRuntimeException。
请注意,如果您只是想捕获所有框架异常,那么为代码生成的异常提供接口可能更好。您可能会捕获该异常,然后是其他异常:
catch(MyException me) {
} catch(Exception e) {
}