2012-05-07 78 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()方法。 –