2012-05-07 76 views
2

我正在設計出一個Android模塊,它執行一些處理,然後使用ORMLite事務寫入數據庫。特別是,我的後臺代碼將如下所示:取消ORMLite寫入後臺線程安全

public class BackgroundOperation implements Runnable { 
     @Override 
    public void run() { 
     //Do some stuff 

     //Write to the database in a transaction 
     try { 

      ORMHelper h = ORMHelper.getDefaultOrmHelper(); 
      final MyModel modelObj = h.myModelDao.queryForId(someId); 
      TransactionManager.callInTransaction(
       h.getConnectionSource(), 
       new Callable<Void>() { 
        public Void call() throws Exception { 
         modelObj.col1 = 10; 
         modelObj.col2 = "hello"; 
         h.myModel2Dao.update(modelObj); 
         h.myModel2Dao.create(new MyModel2("a", "b")); 
         return null; 
        } 
       } 
      ); 
     } 
     catch (Exception e) { 
      return null; 
     } 
    } 
} 

然後將此runnable提交給ThreadPoolExecutor來執行。我希望能夠在需要時取消後臺線程,並試圖確保如果操作被取消,那麼事務將會失敗並且什麼都不做。例如,如果我這樣做:

Future f = myThreadPoolExecutor.submit(new BackgroundOperation()); 

//Some time later 
f.cancel(true); 

我可以確定這將是ORMLite中的事務的全部或全部處理。也就是說,沒有需要清理,我的modelObj既可以設置col1,也可以設置col2,也可以不設置?在捕獲Runnable中的InterruptedException以處理以這種方式取消任務的情況下,我是否必須做任何特別的事情?還是我可以簡單地退出?

回答

2

如果您撥打f.cancel(true),則所有干擾將中斷Thread,這會導致wait(),sleep()和其他一些方法丟失InterruptedException。它會而不是正在取消數據庫事務。

如果你願意,你可以檢查你的IO操作的中間中斷位:

h.myModel2Dao.update(modelObj); 
if (Thread.currentThread().isInterrupted()) { 
    throw new RuntimeException("Thread was interrupted"); 
} 
h.myModel2Dao.create(new MyModel2("a", "b")); 

有關會發生什麼情況的詳細信息,當一個線程被中斷在這裏看到:

What does java.lang.Thread.interrupt() do?


交易AR e當您將多個對象更新爲單個單元或寫入多個表時。請參閱documentation about transactions,其中有一個示例,用於更新交易中的AccountOrder

此外,如果您要更新同一行中的多個字段,則不需要使用事務。更新語句被認爲是一個單元,數據庫應確保該行以原子方式更新。只有在更新多個不同的行時,您才需要在同一張表或單獨的表中進行交易。

+0

謝謝格雷...我的例子有點粗心大意/衝,但重點是如何取消Runnable(尊重數據庫寫入過程中)。我已經更新了兩個單獨的表格編輯,以確保正確性。從你提到的看來,似乎f.cancel()可能不是可靠取消Runnable操作的方式。想知道是否最好創建一個具有同步狀態var的CancelableRunnable子類,該子類指示它是否被取消,並且可以在diff時間檢查並用於退出正常的exec路徑。 – Faisal

+0

我基本上試圖獲得相當於目標c的[nsoperation取消]功能......如果我甚至可以在Runnable期間的戰略時間檢查取消狀態並退出,那就沒問題。 – Faisal

+0

除了'interrupt()'@Faisal之外,沒有辦法在運行時停止Java線程。我已經更新了我的答案。 – Gray

0

ORMLite將利用下面的sqlite交易。這很可能是一個雙階段提交,它只允許你將一個事務作爲一個整體進行提交。

總之,您可以放心,col1和col2只會被修改爲一個單一的原子單位。此外,如果中斷,提交將失敗,對col1和col2的更改將被回滾。

+0

這在一些方面是錯誤的。看到我的答案。這不是一個雙重鎖定事務 - 它只是一個可以提交或回滾的事務。您不需要事務來更新同一行中的多個列。而中斷對交易通話沒有任何影響。它只是中斷'sleep()'或'wait()'。 – Gray

+0

我的意思是說「雙階段提交」(http://en.wikipedia.org/wiki/Two-phase_commit_protocol),它跨越許多不同的數據庫系統,是數據庫確保原子行爲的一種方式。我同意你的意見,在這種情況下事務不一定是需要的,並且如果沒有專門調用isInterupted(),真的沒有辦法中斷run()方法。 –