Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 您能否使用greenDAO将跨不同线程的多个嵌套事务封装到一个整体事务中?_Android_Multithreading_Orm_Transactions_Greendao - Fatal编程技术网

Android 您能否使用greenDAO将跨不同线程的多个嵌套事务封装到一个整体事务中?

Android 您能否使用greenDAO将跨不同线程的多个嵌套事务封装到一个整体事务中?,android,multithreading,orm,transactions,greendao,Android,Multithreading,Orm,Transactions,Greendao,我正在开发一个使用greenDAO作为数据持久层的Android应用程序。应用程序跨多个线程(由线程池确定)从各种不同的源下载数据,使用insertoreplaceintx将每段数据插入事务中的数据库。这很好用 我的问题是,在技术上是否可以使用greenDAO,使用嵌套事务将这些不同的事务(发生在不同线程上)封装到一个整体事务中。我知道在理论上,如果所有事务都发生在单个线程上,那么这是可能的,但是我不确定在不同线程上发生的insertOrReplaceInTx调用是否可能 我希望将它们封装到单个

我正在开发一个使用greenDAO作为数据持久层的Android应用程序。应用程序跨多个线程(由线程池确定)从各种不同的源下载数据,使用
insertoreplaceintx
将每段数据插入事务中的数据库。这很好用

我的问题是,在技术上是否可以使用greenDAO,使用嵌套事务将这些不同的事务(发生在不同线程上)封装到一个整体事务中。我知道在理论上,如果所有事务都发生在单个线程上,那么这是可能的,但是我不确定在不同线程上发生的
insertOrReplaceInTx
调用是否可能

我希望将它们封装到单个整体事务中的原因是,它们表示应用程序中的同步过程。如果导入的任何单个部分失败,我希望中止并回滚整个事务中的所有修改

如果我在启动导入过程的主线程上使用
db.beginTransaction
启动事务,则当另一个线程尝试
insertorReplaceinText
时,会创建死锁


应对这种情况的正确方法是确保所有greenDAO事务都在同一个线程上进行吗?

好的,您不能这样做,因为每个线程都管理自己的连接

如果这些操作之间存在这种依赖关系,您可能希望以任何方式同步它们

e、 g.如果作业A在作业B之前完成,并且作业B的数据库连接失败,该怎么办。您的数据将再次失去同步。另一份工作你还需要一些逻辑。 此外,作家是相互排斥的

我建议创建一个实用程序类,该类可以在事务中运行可运行的列表。每个作业完成后,都会将一个可运行的作业排入此实用程序的队列。这些可运行项包括实际的数据库命令

当最后一个到达时(这取决于您的依赖逻辑),该实用程序将运行事务中的所有可运行程序

示例实现可能如下所示:(我使用了一个简单的计数器,但您可能需要更复杂的逻辑)

classdbbundle{
原子整数;
List mRunnables=new ArrayList();
DbBundle(int numberOfTx){
mLatch=新的原子整数(numberOfTx);
}
作废取消(){
mLatch.set(-1);//因此在submit中减量永远不能达到0
}
布尔值isCanceled(){
mLatch.count()<0;
}
作废提交(可运行可运行){
mRunnables.add(可运行);
如果(mLatch.decrementAndGet()==0){
db.beginTransaction();
试一试{
for(Runnable r:mRunnables)r.run();
db.setTransactionSuccessful()
}最后{
db.endTransaction();
}
} 
}
}
创建每个作业时,传递此共享DbBundle,最后一个将执行所有作业。 所以一份工作看起来像:

....
try {
    if (!dbBundle.isCanceled()) { // avoid extra request if it is already canceled
        final List<User> users = webservice.getUsers();
        dbBundle.submit(new Runnable() {
            void onRun() {
                 saveUsers(users);//which calls db. no transaction code.
            });
    });
} catch(Throwable t) {
    dbBundle.cancel();
}
。。。。
试一试{
如果(!dbBundle.isCanceled()){//如果已取消请求,请避免额外请求
最终列表用户=webservice.getUsers();
submit(新的Runnable(){
void onRun(){
saveUsers(users);//它调用db。无事务代码。
});
});
}捕获(可丢弃的t){
dbBundle.cancel();
}

谢谢,我认为这可能是正确的做法。但我不太理解您关于作业不同步的评论。我可能没有提到每个作业本质上都是将数据写入不同的表,作业之间没有依赖关系,只是所有作业都应在系统中成功完成nc成功完成。如果作业B失败,我希望中止进程并以失败结束事务。顺便说一句,我使用的是我认为您开发的Android优先级作业队列:)哈,是的,这看起来像是由解耦问题引起的:)。您提到过作业a和作业B都应该完成或都失败。即使使用db tTransaction(如果它们正在工作),您需要阻塞JobA直到JobB完成,这不是对作业线程的良好使用(如果依赖作业的数量大于最大消费者数量,则会死锁)。也许我们可以将其集成为对JobManager的扩展。我一直在考虑此类有用的扩展作业。如果您碰巧编写了一个通用的请求,请随时发送请求。我仍然不太确定是否需要阻止JobA(我想我误解了一些东西!)。假设JobA下载一些实体并将其插入数据库。与在JobB中下载的数据没有关系。同时,JobB下载其实体并将其插入数据库。好的,greenDAO确保对数据库的串行访问。因此,假设我们确实有一些方便的方法将所有这些封装到一个整体事务中操作。如果JobA失败,我们将中止整个事务,并取消JobB。这是否可以在不需要同步作业的情况下确保DB数据的原子性?是的,我认为我们在同一页上。我想澄清的是,您仍然需要第三个实用程序类来合并这两个作业的DB事务(如果存在这样的情况,至少在作业之间传递事务引用)。
....
try {
    if (!dbBundle.isCanceled()) { // avoid extra request if it is already canceled
        final List<User> users = webservice.getUsers();
        dbBundle.submit(new Runnable() {
            void onRun() {
                 saveUsers(users);//which calls db. no transaction code.
            });
    });
} catch(Throwable t) {
    dbBundle.cancel();
}