开发者社区> 聚优云惠> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

Android多线程下操作sqlite数据库解决方案

简介: 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qingfeng812/article/details/62217743 问题:Android中的SQLite数据库并发访问 attempt to re-open an already-closed object 因为我们只使用一个数据库连接,Thread1和Thread2的都是由getDatabase()方法返回的相同连接。
+关注继续查看
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qingfeng812/article/details/62217743

问题:Android中的SQLite数据库并发访问

  • attempt to re-open an already-closed object
    因为我们只使用一个数据库连接,Thread1和Thread2的都是由getDatabase()方法返回的相同连接。发生的什么事呢,在Thread2还在使用数据库连接时,Thread1可能已经把它给关闭了,那就是为什么你会得到崩溃异常。

    我们需要确保在没有任何一个人在使用数据库时,才去关闭它。在StackOverflow上推荐的做法是永远不要关闭数据库。Android会尊重你这种做法,但会给你如下的提示。所以我一点也不推荐这种做法。

  • android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5)

    每次都创建了一个新的SQLiteOpenHelper,实际上你每次都创建了一个数据库的连接。如果你在同一时间用不同的数据库连接来对同一的数据库进行写操作的话,那么其中一个会失败。

    解决方案:AtomicInteger

具体模拟代码(Android代码类似):

DataBaseManager

package com.gradle.java.thread;

import java.util.concurrent.atomic.AtomicInteger;

import com.gradle.android.utils.OkhttpUtils;

/**
 * @author Arison
 * 管理sqllite数据库
 */
public class DataBaseManager {

    private static DataBaseManager instance;

    /**
     * 保证多线程下原子操作
     */
    private  AtomicInteger i=new AtomicInteger();

    public static DataBaseManager getInstance(){
        if(instance==null){
            synchronized (DataBaseManager.class) {
                if (instance==null) {
                    OkhttpUtils.println("数据库管理类DataBaseManager--->单例初始化!");
                    instance=new DataBaseManager();
                }
            }
        }
        return instance;
    }

    /**
     * 模拟Android 数据库在多线程下的并发问题
     * @param args
     */
    public static void main(String[] args) {
        for(int i=1;i<=2000;i++){

            new Thread(new Runnable() {

                @Override
                public void run() {
                    //切记,打开,关闭数据库的操作不能直接SQLiteDatabase.getInstance().openDB();SQLiteDatabase.getInstance().closeDB();
                    //必须调用管理者单例类DataBaseManager 来调用打开和关闭操作,从而解决多线程下访问sqlite数据库的问题
                    DataBaseManager.getInstance().openDataBase();
                    DataBaseManager.getInstance().closeDataBase();
                }
            },""+i).start();
        }

    }

    public synchronized AtomicInteger openDataBase(){
        OkhttpUtils.println("+++++++++++++++++++++++++++++++++++++++++++");
        OkhttpUtils.println("线程"+Thread.currentThread().getName()+"--->open开始---->当前数据库连接数:"+i);
        if (i.incrementAndGet()==1) {
            OkhttpUtils.println("线程"+Thread.currentThread().getName()+"打开数据库之前!数据库状态:"
                    +SQLiteDatabase.getInstance().getStateDB());
            SQLiteDatabase.getInstance().openDB();//单例类模拟数据库打开操作
            OkhttpUtils.println("线程"+Thread.currentThread().getName()+"执行数据库打开操作!");
            OkhttpUtils.println("线程"+Thread.currentThread().getName()+"打开数据库之后!数据库状态:"
                    +SQLiteDatabase.getInstance().getStateDB());
        }else{
            OkhttpUtils.println("线程"+Thread.currentThread().getName()+"--->open()操作无效!新增一条数据库连接!---> 数据库状态:"
                    +SQLiteDatabase.getInstance().getStateDB());
        }
        OkhttpUtils.println("线程"+Thread.currentThread().getName()+"--->open完毕---->当前数据库连接数:"+i);
        OkhttpUtils.println("+++++++++++++++++++++++++++++++++++++++++++");
        return i;
    }

    public synchronized AtomicInteger closeDataBase(){
        OkhttpUtils.println("--------------------------------------------");
        OkhttpUtils.println("线程"+Thread.currentThread().getName()+"--->close开始---->当前数据库连接数:"+i);
        if (i.decrementAndGet()==0) {

            OkhttpUtils.println("线程"+Thread.currentThread().getName()+"关闭数据库之前!数据库状态:"
                    +SQLiteDatabase.getInstance().getStateDB());
            SQLiteDatabase.getInstance().closeDB();//单例类模拟数据库关闭操作
            OkhttpUtils.println("线程"+Thread.currentThread().getName()+"执行数据库关闭操作!");
            OkhttpUtils.println("线程"+Thread.currentThread().getName()+"关闭数据库之后!数据库状态:"
                    +SQLiteDatabase.getInstance().getStateDB());

        }else{
            OkhttpUtils.println("线程"+Thread.currentThread().getName()+"--->close()操作无效!关闭一条数据库连接!--->数据库状态:"
                    +SQLiteDatabase.getInstance().getStateDB());
        }
        OkhttpUtils.println("线程"+Thread.currentThread().getName()+"--->close完毕---->当前数据库连接数:"+i);
        OkhttpUtils.println("--------------------------------------------");
        return i;
    }

}

SQLiteDatabase

package com.gradle.java.thread;


/**
 * @author Arison
 * 模拟Android sqlite数据库
 */
public class SQLiteDatabase {

    private static SQLiteDatabase instance;

    private boolean isOpen=false;

    public static SQLiteDatabase getInstance(){
         if(instance==null){
             synchronized (SQLiteDatabase.class) {
                if (instance==null) {
                    instance=new SQLiteDatabase();
                }
            }
         }
        return instance;
    }

    public  void openDB(){
        this.isOpen=true;
    }

    public  void  closeDB(){
        this.isOpen=false;
    }

    public  boolean getStateDB(){
        return isOpen;
    }
}

运行效果图(局部):

这里写图片描述
这里写图片描述

项目代码:

github【Gradle-demo】

联系方式:

见左边栏目

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Android开发重要参考资料
=======================博客============================= 秋百万 有心课堂 郭霖 源码 安装ffmpeg 胡凯 官方培训课程 litesuitsway 爱哥 trinea robinRobin Hu...
740 0
Android ExpandableListView开发简介
 Android ExpandableListView开发简介 我之前写了一些文章是关于实现带有分组、标签的“ListView”: (文章1)《类似通讯录分组的Android PinnedSectionListView,且分组标签悬停滑入滑出》文章链接:http://blog.
720 0
Android大数据、断点续传、耗时下载之DownloadManager开发简介(1)
 Android大数据、断点续传、耗时下载之DownloadManager开发简介(1) Android涉及到的网络数据请求,如果是零星数据、且数据量较小(几十KB到几百KB,1MB以内),一般的,可以自己使用Android原生HTTP或者第三方开源框架如Volley(相关文章:http://blog.
650 0
【Android 应用开发】Android开发技巧--Application, ListView排列,格式化浮点数,string.xml占位符,动态引用图片
【Android 应用开发】Android开发技巧--Application, ListView排列,格式化浮点数,string.xml占位符,动态引用图片
0 0
+关注
聚优云惠
专业科普建站知识 ,让建站变得更简单。专注于WordPress和Java建站知识讲解,云服务器主机知识讲解,建站程序搭建和网站优化。 欢迎访问我的网站 :http://tencent.yundashi168.com
文章
问答
文章排行榜
最热
最新
相关电子书
更多
Android内存泄漏自动化链路分析组件Probe
立即下载
Android开发之多进程架构
立即下载
58同城Android客户端Walle框架演进与实践之路
立即下载