1. 程式人生 > >多執行緒與事務回滾

多執行緒與事務回滾

一、背景:

        使用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<Runnable>(
						queueSize));
Future<String> future = executor.submit(new Callable<String>() {
			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();
}