博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android多线程下操作sqlite数据库解决方案
阅读量:5930 次
发布时间:2019-06-19

本文共 4797 字,大约阅读时间需要 15 分钟。

版权声明:本文为博主原创文章,未经博主允许不得转载。 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; }}

运行效果图(局部):

这里写图片描述

这里写图片描述

项目代码:

联系方式:

见左边栏目

你可能感兴趣的文章
JavaEE学习总结(十四)— 人工智能微博
查看>>
HTML的前世今生
查看>>
工厂模式
查看>>
flexbox父盒子justify-content属性
查看>>
逆向脱壳附加数据处理
查看>>
阿里云启用IPV6
查看>>
intelliJ 打包jar的多种方式
查看>>
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
查看>>
Oracle RAC 实验环境RMAN备份v1.01
查看>>
ControlTemplate in WPF —— ItemsControl
查看>>
把表单转成json,并且name为key,value为值
查看>>
kotlin for android----------MVP模式实现登录
查看>>
.net FrameWork各个版本之间的发展[转]
查看>>
织梦CMS搭建网站必做的服务器相关安全设置
查看>>
张高兴的 Windows 10 IoT 开发笔记:BH1750FVI 光照度传感器
查看>>
SQL Server 服务器主体拥有一个或多个端点无法删除;错误15141
查看>>
Linux-echo、cat命令详解(14)
查看>>
B-树的插入、查找、删除
查看>>
什么是音频视频比特率,采样率,讲的很不错
查看>>
WebApi系列~HttpClient的性能隐患
查看>>