一、背景:
使用javax.jms.MessageListener监听消息,监听到消息后使用线程执行器ThreadPoolExecutor进行业务处理,并配置了事务JmsTransactionManager,当业务处理出现异常时,进行回滚操作。
二、问题:业务中可能出现的两类异常:
1.业务处理出现checked exception必须在线程中捕获处理不允许抛出;
2.如果线程抛出unchecked exception,则线程终结,主线程不受影响。
基于以上对线程处理异常的认识,可以确定使用多线程处理业务中出现的异常在主线程中无法捕获,即无法实现回滚。
三、解决办法:
使用Callable接口(Executor Framework的优势之一:可以运行并发任务并返回结果)。
线程执行器业务处理代码:
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize,
KEEP_ALIVE_TIME, UNIT, new ArrayBlockingQueue(
queueSize));
Future future = executor.submit(new Callable() {
public String call() {
try {
……
} catch (Exception e) {
//捕捉到异常时进行异常处理并返回failed
return “failed”;
}
//业务处理正常则返回success
String result = "failed";
try {
//通过回调获取线程执行是否出现异常
result = future.get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
});
监听器实现事务回滚代码:
// 消息进行业务处理并返回处理结果,sucess(成功),failed(失败)
String result = serviceConfiguration.getServerProcessThreadPool().process(message);
// 获取到业务处理异常时即result为"failed",抛出运行时异常进行事务回滚
if ("failed".equals(result)) {
throw new RuntimeException();
}