Android多线程下操作sqlite数据库解决方案
来源:互联网 发布:全国软件学院排名 编辑:程序博客网 时间:2024/05/20 22:40
问题: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】
联系方式:
见左边栏目
0 0
- Android多线程下操作sqlite数据库解决方案
- 测试在多线程下操作sqlite内存数据库(转)
- 测试在多线程下操作sqlite内存数据库
- QT5 下操作sqlite数据库
- unity3d在android环境下操作sqlite数据库
- ubuntu android 命令环境下操作sqlite
- sqlite命令行下操作
- android下操作FrameBuffer
- android下操作FrameBuffer
- android下操作FrameBuffer
- android下操作FrameBuffer
- android下操作FrameBuffer
- ubuntu下操作mysql数据库
- linux下操作informix数据库
- linux下操作mysql数据库
- DOS下操作MySQL数据库
- 图形界面下操作Mysql数据库
- cmd下操作mysql数据库
- SSH框架搭建流程(注解的方式创建Bean)
- keepAlived应用于HaProxy的主备自动切换实现高可用,避免单点故障
- linux下显示git当前分支
- 【Best Practice】基于阿里云数加·StreamCompute快速构建网站日志实时分析大屏
- Bulk insert如何导入部分字段的数据
- Android多线程下操作sqlite数据库解决方案
- Rocksdb 代码学习 写流程2 (memtable写)
- java自适应响应式 企业网站源码 SSM 生成静态化 手机 平板 PC
- collection
- BatteryModel
- Serverless理念的弄潮儿—— 阿里云数加平台助力大数据普惠
- Java指令重排序
- SQL约束Constraints
- 卷积神经网络(三)